Monday, August 02, 2004

A few days ago, I posted a blog entry mentioning my foray into SCM systems.  The purpose of the investigation was two-fold: 1) to move away from VSS (Sourcesafe) and 2) to enable remote source code access.  I work with a client out in California routinely and using VSS is impractical in this situation.  It didn't make sense not being able to sync up our code every couple weeks when I went to Santa Barbara, and then when he travelled here to SLC not having a SCM...well, let's just say that it hampered our work.  Yes, we found ways to work around the system and we've been pretty effective, but it became too painful, plain and simple.

We considered using SOS (Source Offsite).  SOS runs as an agent over a VSS repository, TCP/IP enabling it.  This would be great - except that we'd still be using VSS which would have violated goal #1.  At my previous employment we used SOS in maintaining source code and sharing it with our remote client site.  It worked well, but VERY slow.  Now, if I'm not mistaken, the server was patched, rebuilt, or something and the perf was noticeably better.

Of the SCM systems we were investigating, the two that stood out the most were SourceGear's Vault and PerForce.

I've heard nothing but good about PerForce.  There seems to be a very strong community backing.  I downloaded it and started to play with it.  To be honest, I really liked it, though it was at first a bit confusing.  I attribute the confusion to my VSS background.  In PerForce the terminology is quite different from VSS (e.g. 'Open for Edit' vs 'Check Out', 'Submit' vs 'Check In'), but I found a terminology differences document and that helped substantially.  Once you look at it and think about it, though, it's really not that bad.  After installing a Visual Studio plug in, I was up and going.  I was very impressed with the speed and ease of use of PerForce (even though I was running it on a Virtual PC).

Vault, on the other hand, is a relative newcomer to the SCM world.  Written purely in C#, and backed to SQL Server, this was an intriguing offering.  After downloading the single-user trial (free BTW) and playing with it I fell in love with it.  Perhaps the biggest advantage to my getting up and running here was that it was built to look and feel like VSS.

We decided to go with Vault as our SCM system for the following reasons.  PerForce offers many of the same capabilities, so this list isn't a set of “Vault has these and PerForce doesn't“ features.

  • Familiarity (no learning curve)
  • TCP/IP capabilities
  • Transactional check-ins
  • Simplicity to install
  • The backing database automatically incorporates itself into my database backup maintenance plan
  • Price ($)
  • The ability to turn off Vault being my primary SCM (I didn't see this anywhere in PerForce).  That way, I can still fall back and use VSS for my own and legacy projects - very important!
Monday, August 02, 2004 4:03:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Wednesday, July 28, 2004

No doubt if you dabbled around in .NET you've come across an attribute in the System namespace called CLSCompliantAttribute (CLSCompliant for short). If not, try running FxCop against your code once in a while - you'll see it real quick. The CLS in this context doesn't mean 'CLear Screen'. Instead it is short for Common Language Specification.

What is the Common Language Specification you ask? Well, in brief, the CLS helps ensure interoperability between languages by defining basic language features and rules; it is a subset of the Common Type System (CTS). Code that is CLS-compliant is guaranteed to be accessible from another CLS-supporting programming language. This level of support and interoperability is fantastic.

If, when writing code you conform to the CLS rules, you forget to add the CLSCompliantAttribute to your assembly, your assembly is NOT compliant. However, if you take the time and effort to add the attribute to your assembly you enter a world where you must now ensure compliance in all types, or at least explicitly identify those that aren't. The same holds true for a type. If you mark a type (i.e. class, struct, interfaces, etc) as CLS-compliant, you must mark all non-CLS-compliant members. Alternatively, you could fix up your code to be CLS-compliant; there is usually a CLS-compliant mechanism that provides the same capabilities.  Types that derive from non-compliant types are inherently not compliant and should therefore also be marked as such.

All you need to do to apply the attribute to your assembly is the following:

using System;
[assembly: CLSCompliant(true)]

As a best practice, I highly encourage you to add this attribute. It will definitely facilitate reuse of your components, and causes the C# compiler to check for compliance in all types.

But what are some of the rules associated with CLS compliance? What constitutes a non-compliant entity? Let's check it out.

   1. Naming conventions: protected or public identifiers must begin with a letter. For example, you can't begin an identifier with an underscore.

   2. Uniqueness of names: in order for a type to be CLS-compliant, it cannot contain members that differ in name solely by case. For example, the following is invalid:

class MyClass {
   protected int value;
   public int Value;
}

   Some languages (such as C# support this), but it's not CLS-compliant, so an alternative might be the following (ok, I know, it's a lame example):

class MyClass {
   protected int val;
   public int Value;
}

   3. Data types: variables of the unsigned varieties (e.g. uint, ulong, etc) are not CLS-compliant. If you expose an unsigned integer from a protected or public member, your type will not be compliant. Instead, consider using the signed variety.

I don't pretend to be exhaustive with this short set of rules, but these are the ones with which I believe most developers will run into trouble. For a more comprehensive view, check this out.

Perhaps it's important to mention that these rules (for the most part) apply only to protected and public members; these are the members that other CLS-compliant langauges will be using to interact with the objects.  You can do what you want in private fields, variables, methods, types, etc.

Wednesday, July 28, 2004 4:53:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, July 26, 2004

Over the years I've been a user of Microsoft's SourceSafe.  Mostly this is because the tool was there and was free (well, it was part of the Visual Studio family of tools).  While for the most part this experiece has been a good one, I have had my fair share of mishaps and issues (mostly regarding web applications).  I'm not going to take the time to delve into these issues as they are incredibly frustrating and I'd spend the time venting, which is not what this blog is about.  I am wanting to get away from VSS for a variety of reasons and am looking into other solutions.

I'm in the process of evaluating other SCM packages and was wondering what your experiences have been with each.  I'm looking for constructive, decision-making feedback.  I'm in the process of evaluating Sourcegear's Vault, and was wondering if anyone has had any experiences (good or bad) with it.

1) VSS
2) Source Depot
3) Perforce
4) CVS
5) Vault
6) Other...

Monday, July 26, 2004 9:51:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [4]  |  Trackback
 Friday, July 23, 2004

One of the greatest personal challenges of mine with respect to code (or anything over which I feel ownership) is that of letting go and allowing others to edit, enhance, or in any way modify it.  This is not a quality that I find attractive or endearing, but more of a hurdle.  I do have the experience (many times over I might add) of working in a team environment on a product - but that's different at some level.  In that scenario there's more of a feeling of 'team ownership' despite the fact that I 'own' an area or an aspect of code.

I have several personal side projects that I (along with a friend) have been working on for quite some time.  I have 'ownership' of about 95% of the code - that is, I wrote it, I designed it, I conceptualized it - it's my baby.  Recently, my friend and I extended an invitation to three other mutual friends to join us in developing this software...this was great in concept.  I've always tried to be an includer, so no problem.  However, my heart stops or occasionally skips a beat when these other associates start dabbling in this code that I've had almost exclusive ownership of for the past millenium.  I'm really working hard at overcoming this perceived weakness and feel that I'm conquering it - but it's hard.

What can I do to convince myself that these other contributors will surprise me and write great code without my meddling?  I believe I need to educate them on the initial ideas and concepts and direction and then simply have a degree of trust and confidence.  It's mostly a matter of trust and learning to let go.

Friday, July 23, 2004 5:47:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Thursday, July 22, 2004

You ever have the need to validate whether the user entered a valid IP address?  Regular expressions come in really handy here.  However, if you do some searching online for a good regex to accomplish this, you'll undoubtedly come across some regular expressions that are pretty lousy or only half-baked.

When validating an IP address, we only want to accept values between 0.0.0.0 and 255.255.255.255.  I wrote the following function which seems to do the trick nicely:

[UPDATE: 09/28/2006]

As mentioned by a few of the readers, my initial regular expression was shortsighted and I overlooked a subset of numbers.  I've updated my solution to use a suggestion by AleXX below, which correctly validates an ip address from 1.0.0.0 to 255.255.255.255.

Thanks for the observations, guys, and the corrections.  I'll be more thorough in the future.

public bool IsValidIPAddress(string ipAddr) {
  
string pattern = @"^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$";
  
Regex reg = new Regex(pattern, RegexOptions.Singleline | RegexOptions.ExplicitCapture);
  
return reg.IsMatch(ipAddr);
}

Thursday, July 22, 2004 7:06:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [12]  |  Trackback

Now that I'm back from the funeral and back in action I thought I'd create a post that hopefully will prove to be helpful to someone out there in the cyberworld seeking guidance.  This one's regarding constructors.

A while back, while dabbling in the realm of constructors, I came upon a little tidbit that I haven't seen documented - not that it isn't documented, I just didn't go searching for it.  If you have a class (or a struct) in which you have several overloads on the constructor where each constructor does a lot of the same work, you can save yourself some headache.  In a fashion similar to how you call the base class's constructor, you can call another constructor by simply calling the this(...) method.  So instead of having code that resembles the following:

public sealed class Customer {
   private string _name;
   private DateTime _startDate;

   public Customer(string name) {
      _name = name;
      _startDate = DateTime.Now();
   }

   public Customer(string name, DateTime startDate) {
      _name = name;
      _startDate = startDate;
   }
}

you have code that looks like this:

public sealed class Customer {
   private string _name;
   private DateTime _startDate;

   public Customer(string name) : this(name, DateTime.Now()) { }

   public Customer(string name, DateTime startDate) {
      _name = name;
      _startDate = startDate;
   }
}

Granted, this is a simplistic case that doesn't really do much, but it saves the burden of repeating code unnecessarily and give you the benefit of having a single working constructor (or at least just a few) which greatly simplifies the readability of your code.

Thursday, July 22, 2004 5:43:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Thursday, July 15, 2004

Today has indeed been a somber day.  Today just before 4:00 PM my beloved grandmother (Granny) passed away.  Up until just a few days ago she's been as active as ever, only just recently a dormant cancer finally caught up to her.  Granny was a wonderful person, a devoted mother and grandmother, and  genuine saint.  Granny leaves behind an incomparable legacy.  We were planning on traveling down to Las Cruces, NM tomorrow to see her as we knew she was ill, but as fate would have it that was not to be.  Instead, we will be traveling down on Sunday for the Tuesday funeral.

I feel genuinely blessed to have known Granny as well as I did - I have many wonderful memories taking care of her garden, playing her piano, doing puzzles with her, and hanging out.  I vividly recall spending (almost) every Sunday evening at her house while growing up.  There we would eat her famous beans, Pa would pop popcorn, and we'd watch Laurence Welk, The Wonderful World of Disney, and Mutual of Omaha's Wild Kingdom.  We would play in the backyard, climb her trees, and build forts and haunted houses in the basement.

I had the privilege of going down to Las Cruces with my previous company in January.  That turned out to be my farewell visit and I am very grateful for it.

Granny and Pa had five children - 4 daughters and a son.  Twenty seven grandchildren and I don't know how many great-grandchildren.  At our family reunion last November we had 96 people there - direct descendants and their spouses - and not quite everyone was accounted for.  What a wonderful experience.

Granny, we love you and are deeply honored to have you as our grandmother.  Your devotion to family and church was amazing.  You will be remembered for so many things: your gardens, your wonderful Thanksgiving dinners, your charity, your beans, your basement where we built many a haunted house, your puzzles, your backyard, your incomparable quilts, and much, much more.  But most of all you will be remembered for being our Granny.  We love you very much.

Thursday, July 15, 2004 4:50:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, July 12, 2004

Back in the days of being a trainer, I used to stand all day long.  Back in those days I was accustomed to it.  I'm spending all day in the booth and while it is great and exciting to talk to people about our killer app my feet are dying.  Note to self: next time at a conference wear shoes that not only fit and aren't a 1/2 size too small, but are comfortable also.

Monday, July 12, 2004 3:30:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback

Here I am, continuing in Toronto at the Microsoft Worldwide Partner Conference.  This has been awesome!  While I have a hard time with the 'sales' side of the house (being almost exclusively dev) it is awesome to see the interest and rallying support around our system.  Our web product is receiving rave reviews from customers as well as some very high marks from the CRM team.  We met with Jason Hunt (Technical Product Manager for CRM) and he loves the product.  Additionally, we've met with Brenda Smestad, Barry Givens (who gives us very high reviews and lots of kudos), Graham Sheldon, and others.  It has been awesome!

I've also continued to run into people that I know - which is great!  Today I saw (though he didn't see me) a great friend Dan Peay of Microsoft.  I hope to run into him later and catch up.  Also ran into Michael Reagan (now with Microsoft New York) - what a great guy!  I really remember having a blast with these guys from MS and it really means a lot to me that they not only remember me but have come back to talk and recall the good ol' days.  These are good times!

Monday, July 12, 2004 5:17:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, July 10, 2004

Well, my conference here in Toronto is, to say the least, has been eventful.  To start off, I owe a lot of thanks to customs in Canada.  I didn't realize upon coming that I needed a passport.  It may have been pure dumb luck or whatever, but before coming I remembered to grab mine.  Unfortunately, my passport has been expired for 3 years.  I got a big fat warning prior to leaving that if customs didn't want to let me in the country, I'd spent the night in a cell and be deported.  Needless to say, this had me a little worried upon entering the country.  Well, when I nonchalantly handed my passport and papers to customs the lady (a mighty severe-looking woman I might add) gave my passport a double check, thought about it for a bit, and then just let me in! Whew!  She only asked me what I was in the country for.  That was a relief.

I'm pretty excited to be here at the Microsoft Worldwide Partner Conference.  Though it's very sales-oriented (something that is very hard for me to deal with), I'm having a good time.  We spent the day setting up our booth and meeting with MS partners.  There is a lot of interest revolving around product configurators which is very reassuring and exciting.  I see lots of potential with our product and am extremely excited about our future prospects.

Upon making preparations for this trip/conference I suspected that I might run into friends here - I always do when I come to conferences.  As it turns out my luck still runs hot!  Today I ran into two good friends and associates from my days at Microsoft: Larry Shaw and John Herman.  Additionally I encountered Kristi Schwartz.  It was pretty invigorating to see my good friends.  I hope to see them at the booth to show them what I've been working on and catch up on old times.

Looking forward to a good conference!

Saturday, July 10, 2004 4:19:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback