Tim Hibbard

Software Architect for EnGraph software


News





Add to Google



My Stats

  • Posts - 593
  • Comments - 338
  • Trackbacks - 507

Twitter












Tag Cloud


Recent Comments


Recent Posts


Article Categories


Archives


Post Categories


Image Galleries


EnGraph Blogs


Links


Other


Roll


May 2007 Entries

Another EnGraph wedding


Last year, Kyle and Allie got hitched, and tomorrow, David (one of our AutoCAD studs) is marrying Becca.

Congrats David!  I guess that leaves me as the last stud in the stable :)

Technorati tags: , ,

posted @ Saturday, May 26, 2007 4:18 PM | Feedback (0) |


Prairie Dunes


pd

Last weekend, I had the chance to play the beautiful Prairie Dunes golf course in Hutchinson, KS.  They have hosted several pro events, including the 2006 Senior Open.

The course was in perfect condition.  The fairways are tight, the greens are vicious and bunkers are everywhere.  I ended up hitting only 5 greens in regulation and missed all of my birdie attempts.  I kept my score under 100 though, and walked away with a 95.

More pictures here.

 

DSC00660 DSC00663

DSC00665 DSC00669

 

Technorati tags: , ,

posted @ Friday, May 25, 2007 4:22 PM | Feedback (1) | Filed Under [ Sports ]


300 Unit tests


I just wrote the 300th unit test for our version 4 of ParaPlan (GoldStar).

We are about 6 months into the project, 85K lines of code and 60% code coverage on the non-UI stuff.  Our first release to alpha testers is July 1.  Hopefully, I'll have closer to 85% coverage by then.

posted @ Thursday, May 24, 2007 9:59 PM | Feedback (0) | Filed Under [ .NET Goldstar ]


C# code to rebuild properties after implementing INotifyPropertyChanged


I wrote some code that is meant for people that want to easily implement INotifyPropertyChanged after using the "prop" code snippet.  It will take code that looks like this:

public int DriverID
{
   get { return _driverID; }
   set { _driverID = value; }
} 

And return it like this:

public int DriverID
{
   get { return _driverID; }
   set
   {
      _driverID = value;
      OnPropertyChanged("DriverID");
   }
}

It also will ignore any triple slash comments and #regions.  So you can copy your entire #region --Properties-- into the class and it will return a #region --Properties-- with the new OnPropertyChanged code.

The article with the code is here.

 

Technorati tags: , , ,

posted @ Thursday, May 24, 2007 9:43 AM | Feedback (0) | Filed Under [ .NET ]


EnGraph in Reno


Via Kyle Archer, our sales guys are at the CTAA Expo this week in Reno, NV. 

Check out our booth if you are around!

 

posted @ Wednesday, May 23, 2007 8:57 AM | Feedback (0) |


Casting an interface to the original type


I have an interface IEntity that all my state objects like Client, Vehicle, Route etc implement.  I am creating a control with a DataGridView that will display information about a list of state objects.  The control expects an IEntity object, but since IEntity only defines methods, nothing is displayed on the DGV when I bind it to List<IEntity>, even though I can see the .DataSource is properly set when I view it in the debugger.

I need to cast my object back to it's original type, so it's properties can be displayed in the DGV.  The code that populates the DGV will not know what the original type is so I can't simply down cast it.  I know there is a simple way to do this, I just can't seem to find it.

The code I have now looks like this:

 

List<IEntity> results = MyAnonDelegate.Invoke(); dataGridViewResults.DataSource = results;

MyAnonDelegate is obviously an anonymous delegate that is passed to the control to tell it where to get it's data from.

Somehow, I need to get a List<T> where T = the original state object that implements IEntity.  Any pointers?

 Update:  I reached my desired result, but it doesn't seem very elegant.  I used results.ConvertAll and casted each IEntity to an object and my DGV renders it correctly.  Here is the code I used:

List<object> ds = results.ConvertAll(new Converter<IEntity, object>(
 delegate(IEntity ent) { return (object)ent; }
        ));
dataGridViewResults.DataSource = ds;

 

posted @ Friday, May 18, 2007 10:41 AM | Feedback (0) | Filed Under [ .NET ]


Peace out NewsGator


I've been using NewsGator for a while now (my post about switching to it), and it's not bad, but I discovered the mobile version of Google Reader last night.  This morning I found the Homepage reader widget and that was the nail in the coffin of NewsGator.  The mobile version works so slickly on my PPC6700 and I've always liked the UI of the web version.

So thanks NewsGator, you've been good, but I'm all google now.

 

Technorati tags: , ,

posted @ Wednesday, May 16, 2007 5:06 PM | Feedback (4) | Filed Under [ Mobile ]


Google Suggest


I've finally made it!  Google Suggest will recommend "Tim Hibbard" after typing "tim hib" and will recommend "Where's Tim Hibbard" after typing "wheres ti".

 :)

Technorati tags: ,

posted @ Tuesday, May 15, 2007 7:57 AM | Feedback (2) | Filed Under [ Where's Tim ]


Update to SQL connection string validation code


Chris (who I meet down at SC Code Camp 2006) left a comment on my C# connection string validation code pointing out some flaws in my code.  He suggested playing with System.Data.SqlClient.SqlConnectionStringBuilder

I redid the code to take advantage of this helper class.  Here is the updated version of the code.  Note that I only validate Data Source, Initial Catalog, User ID and Password because that is the only thing our software uses right now.

public static bool IsValidSQLConnectionString(string cn)
{
    bool rv = true;
    try
    {
        SqlConnectionStringBuilder sqlSB = new SqlConnectionStringBuilder();
        sqlSB.ConnectionString = cn;
        if (string.IsNullOrEmpty(sqlSB.DataSource))
        {
            throw new ApplicationException("Data Source missing");
        }
        if (string.IsNullOrEmpty(sqlSB.InitialCatalog))
        {
            throw new ApplicationException("Initial Catalog missing");
        }
        if (string.IsNullOrEmpty(sqlSB.UserID))
        {
            throw new ApplicationException("User ID missing");
        }
        if (string.IsNullOrEmpty(sqlSB.Password))
        {
            throw new ApplicationException("Password missing");
        }
    }
    catch (Exception)
    {
        rv = false;
    }
    return rv; 
}

 

posted @ Monday, May 14, 2007 2:59 PM | Feedback (6) | Filed Under [ .NET ]


Help installing CF 2.0 SP1 on my device


I'm having trouble installing .NET Compact Framework 2.0 Service Pack 1 on my PPC6700.  I want to play with the new version of NavXS, but when I try to download the framework from here, the installer tells me:

cf_installer

Any ideas on how to load the framework on my PPC?  I haven't been able to find a cab file anywhere.  Is it a Vista thing?

 

Technorati tags: , ,

posted @ Monday, May 14, 2007 7:52 AM | Feedback (2) | Filed Under [ .NET Mobile Social Geocoding Vista ]


C# Code to validate SQL Connection Strings



Update - I made the code better here

Here is a code snippet I use to validate SQL connection strings:

 

/// <summary>
/// Checks a connection string for validity
/// </summary>
/// <param name="cn">SQL Connection string to validate</param>
/// <returns>True if connection is valid.</returns>
/// <history>
/// [Tim Hibbard] 12/03/2006 Created
/// </history>
public static bool IsValidSQLConnectionString(string cn)
{
bool RV = true;
try
{
if (!cn.Contains("Data Source"))
{
throw new MissingMemberException("Missing Data Source");
}
if (!cn.Contains("Initial Catalog"))
{
throw new MissingMemberException("Missing Initial Catalog");
}
if (!cn.Contains("User ID"))
{
throw new MissingMemberException("Missing User ID");
}
if (!cn.Contains("Password"))
{
throw new MissingMemberException("Missing Password");
}
string[] contents = cn.Split(char.Parse(";"));
if (!contents[0].StartsWith("Data Source"))
{
throw new MissingMemberException("Missing Data Source");
}
if (!contents[1].StartsWith("Initial Catalog"))
{
throw new MissingMemberException("Missing Initial Catalog");
}
if (!contents[2].StartsWith("User ID"))
{
throw new MissingMemberException("Missing User ID");
}
if (!contents[3].StartsWith("Password"))
{
throw new MissingMemberException("Missing Password");
}
}
catch (Exception)
{
RV = false;
}
return RV;
}
 
Technorati tags: , , ,

posted @ Thursday, May 10, 2007 7:56 AM | Feedback (3) | Filed Under [ .NET ]


Support GWB on Digg


Some really content come out of GeeksWithBlogs. One of the best ways to spread that information to the rest of the community is via Digg.

Via this search, you can search stories submitted to Digg that have the url "geekswithblogs".  You can also get the same search via RSS

Help your fellow geek bloggers out and digg posts that you find interesting.

 

Technorati tags: ,

posted @ Wednesday, May 09, 2007 4:08 PM | Feedback (2) |


Testing post draft with WLW


Just curious if the "Post Draft to Weblog" works as expected in Windows Live Writer...

Update: it does work....Very cool.  It will put the post in your Posts tab.  When you are ready to publish it, just click "edit", make your changes, check "Published" and "Syndicate on Main Feed" on the Advanced options, and push "Post"

posted @ Wednesday, May 09, 2007 12:44 PM | Feedback (0) |


Slow internet


Ever since moving to Lenexa, our internet has been really slow.  In Lawrence, I was getting about 6.5 mb/s down and 760 kb/s up.

Now I'm getting:

 

Any suggestions for a better ISP in Johnson County?  We are with SBC now and our contract expires this year.

 

Technorati tags: , ,

posted @ Wednesday, May 09, 2007 12:17 PM | Feedback (1) |


WM5 tip - deleting multiple messages


On Windows Mobile 5 devices with a keyboard, you can hold the Shift key and select multiple messages in the email client.  When you have multiple messages selected, you can press Menu -> Delete to delete these selected messages.

Hope this saves somebody as much time as it has saved me.

 

Technorati tags:

posted @ Wednesday, May 09, 2007 7:45 AM | Feedback (1) | Filed Under [ Mobile Keyboard Shortcuts ]


Solution to my TFS architecture problem


A while ago, I blogged about how I was having problems with how I set up references when we switched over to Team Foundation Server.  I was linking internal dependencies to the build folder on the build server.  This caused excessive network traffic (and delays when working from home) and failed builds (because TFS couldn't clean the build folder if I have a solution open with a reference to that folder).

I've since found this branching guide on CodePlex.  This has fixed all my problems.  It took me almost full day to switch all my team projects to their style, but I've been using this standard for a month now and the dividends have been substancial.

In case you didn't follow the link, the cliff notes are to have a lib and a shared code folder (along with others) in your source control for each team project.  The lib folder contains binaries and your shared folder contains branches from other team projects.  I took it a step further and created a monster solution for my major projects and added all the projects from the shared code folder.  I then re-mapped my references from the dll on the server to the projects in my solution and I now have zero network dependency when I build my solution.  It's fast, it's clean and the projects in my shared code folder will update (manually) when I add changes because it's just a branch from the original code.

Much thanks to the guys that put out articles like this.

 Update - Changed the link to a better article

posted @ Tuesday, May 08, 2007 5:21 PM | Feedback (0) | Filed Under [ .NET TFS ]


My favorite Visual Studio keyboard shortcut


I actually have two favorite keyboard shortcuts that I use all the time.

When defining a class signature that will implement an interface or abstract class (class something : ISomethingElse),  you can press SHIFT - ALT - F10 then ENTER after you populate the signature and it will populate the needed method signatures for you.  I know it sounds a bit hairy, but you get used to it pretty quickly.

My second favorite is CTRL - TAB to cycle through the open tabs in the IDE.  This also works for any tab control.

 

posted @ Monday, May 07, 2007 9:04 PM | Feedback (4) | Filed Under [ .NET Keyboard Shortcuts ]


Why I don't use open source in production desktop apps


I've thought about posting this for a while now and responses to my architecture post by Dave and Dru have got me thinking about it again.

I avoid open source frameworks or libraries in our production desktop applications.  I don't have a problem with third party when it comes to web applications or internal apps.  I use AjaxPro and skmRSS on Where's Tim and my home site.  I use Indy.Sockets all the time in our internal apps.

Where's Tim is just for fun though and if it goes down, it's not that big of a deal.  And our internal apps mostly just automate things that could still be done manually.  When it comes to production applications, the apps that pay my salary, I get a bit possessive over what we deliver.  ParaPlan isn't a helper application.  It's is an agency's backbone.  Our client's entire lifecycle of doing business is generated by, or inputted into ParaPlan.  If our software runs into a bug and one person can't do their job, then everybody else's job is impacted by it.  Kyle and I give all of our clients our cell phone numbers, and when something goes wrong, we get called and they have to pause their operation until we get it fixed.

For me to properly support our clients, and to keep my cell phone minutes under the allotted bucket, I need to understand everything that our code is doing.  I don't feel comfortable using third party code because I don't always know the author's true intentions.  Generally, it is intuitive and 99% of the time, it works.  But I don't like taking the chance that it might not.  We also have unit tests and pre-deployment processes that should catch most problems, but just because it worked on my machine and it compiled on the build machine doesn't mean it's rock solid.  I don't want to be staring at a function at 9:00 PM on a Friday wondering why it's not working on a client's machine and trying to determine if it's my fault or a third party's library's fault.  And I don't to be the one trying to explain to the client why I used somebody else's code and that's why they can't do their job. 

I also feel that third party library's can limit your scalability.  It's just another link in the dependency chain that could be broken as you adapt new technology.

The third reason why I avoid open source is purely selfish.  I want to be the best developer I can be, and I would rather learn how to code the functionality than use somebody else's code.  That might mean that it initially takes me longer to push something out the door, but it makes me smarter and more valuable to EnGraph. The next time I'm faced with a similar problem, I'll be able to use the knowledge that I learned instead of throwing a third party library at it.

I do use the Enterprise Library in my production apps.  I feel better knowing that it is delivered by Microsoft.

In no way is this a knock against people that consume or develop open source libraries.  I'm not scared of proprietary information, I post my code all the time.  I also pick apart code from open source libraries to understand what they are trying to accomplish.  I think the open source community is a great thing.  It's just not something I want to use.

 

posted @ Monday, May 07, 2007 2:19 PM | Feedback (6) | Filed Under [ .NET Where's Tim Goldstar ]


PPC6800 in October 07


ppc-6800

PhoneNews.com reports that Sprint has delayed releasing PPC-6800 until October of this year.  This release date will enable the phone to use EVDO rev A and also will be loaded with Windows Mobile 6.

I can wait a couple months, I just hope my PPC6700 can hold on until then.

 Update - Looks like it has been bumped up to June 2007

 

Technorati tags: , ,

Trackback

posted @ Monday, May 07, 2007 8:51 AM | Feedback (1) | Filed Under [ Mobile ]


Golfing at Eagle Bend


Kyle, Matt Prentis and I are golfing at Eagle Bend this afternoon.

They are much better than me.  It's going to be a loooong day.

Matt needs to start blogging.  He does all kinds of cool stuff with Java, Web Services and SharePoint Webparts.

 

posted @ Saturday, May 05, 2007 12:12 PM | Feedback (0) | Filed Under [ Sports ]


Architecture thoughts and Reflection


When we decided that ParaPlan 4.0 would be rebuilt in .NET (from Access), we decided not to redesign the SQL database.  Even though we have some inefficiencies in our db we want to decrease development time and allow our beta testers to be able to switch back and forth between our Access front end and our .NET front end.

As development began, we decided that we needed an object for each table and that we could eliminate some of the database inefficiencies in our objects.  So we have an Appointment object that represents our Appointments table, but where the Appointment table has Address1, Address2, City, State, etc, we would create a Location object that we could reuse everywhere we talked about locations.  As another example, we created a Client object that represented the Clients table, but we would use the Client object in other tables.  So instead of Appointment.ClientID, Appointment.ClientFirstName, we would have Appointment.Client.ID and Appointment.Client.Name.FirstName, etc ,you get the point.

I had a good talk with Dave Donaldson at HDC 2006 about removing functionality from entity objects and letting them just hold data.  I then created EntityManagers for each EntityObject and put all the functionality on the manager side.  I soon got tired of instantiating an EntityManager every time I wanted to do a simple task like save or delete an object's record from the database, so I created "function pointers" that live in the state object, but point to the appropriate entity manager.  So I would have code in the state object that looked like this:

public int Save()
{
    return new Managers.AppointmentManager().Save(this);
}

public bool Delete()
{
    return new Managers.AppointmentManager().Delete(this);
}

This way, all the functionality still lives in the manager, but you can perform simple tasks from the state object.

We also wanted to be able to easily populate an object from the database.  Our Appointments table only stores a little information about the Client (first name, last name and ID), so if we populated an Appointment object from the database, we would have Appointment.Client, but Client would be underpopulated and calling Appointment.Client.HomeLocation would return empty information.  To get the rest of the information, we would have to instantiate a ClientManager, populate a Client object and assign it to Appointment.Client. 

So, I added a .Populate to my IEntity interface that all the state objects implement.  In the implementation, I would do the dirty work of creating a ClientManager, populating an object and assigning the properties of the new object to the current object.  That way, we could call Appointment.Client.Populate() and all the information about that client would live in the object (provided that ID or other identifying information existed in Appointment.Client).

As I was implementing the .Populate into our state objects, I realized that I was going to spend a lot of time going through each property and assigning it to this.  So I started playing around with System.Reflection and realized that I could create a single function in my base class that would accept an object as a parameter, iterate through it's properties and try to assign it to this.  So I added a function that looks like this:

internal bool Build(object obj)
{
    bool rv = false;
    try
    {
        if (obj == null)
        {
            throw new ApplicationException("obj is null");
        }
        //iterate through each property of this
        foreach (System.Reflection.PropertyInfo prop in this.GetType().GetProperties())
        {
            //get the name of the current property
            string memberName = prop.Name;
            //make sure this property is writeable and the obj property is readable
            if (prop.CanWrite && obj.GetType().GetProperty(memberName).CanRead)
            {
                //Get the value of this current property from obj
                object objValue = obj.GetType().GetProperty(memberName).GetValue(obj, null);
                //Set the value of this property from obj
                prop.SetValue(this, objValue, null);
            }
        }
        //if we are here, everything worked
        rv = true;
    }
    catch (Exception)
    {
        //something bad happened, return false
        rv = false;
    }
    return rv;
}

So now, when somebody calls Appointment.Client.Populate() the code to do the work is very simple:

 

public bool Populate()
{
    return base.Build((Client)new Managers.ClientManager().GetByID(this._id));
}

So the code creates a new ClientManager and calls GetByID, which hits the data access layer and returns an IEntity (the interface that all the state objects implement).  I cast the IEntity to a Client and send it to the base class to transfer the properties.

Obviously, I will need to add some code to ensure that this._id is populated and catch exceptions to throw to the calling code, but if the calling code just needs to know if it ended up getting populated, one line of code will work just fine.

So far it is working out really well.  But, this is my first real crack at reflection, so I would appreciate any pointers.

 

posted @ Friday, May 04, 2007 10:31 AM | Feedback (3) | Filed Under [ .NET Goldstar ]


Best code formatter live writer plugin


I've used several different code formatters in Windows Live Writer and have finally found one that I really like:

http://www.codeplex.com/insertcode

 

posted @ Friday, May 04, 2007 7:52 AM | Feedback (0) | Filed Under [ .NET ]


Giddy with Reflection


I'm not being narcissistic, I just discovered tonight that I'll be able to save over 5000 lines of code on my current project using System.Reflection to internally populate an object from an external object of the same type.  I'll post some code later so the true gurus can pick it apart.

 

posted @ Thursday, May 03, 2007 11:21 PM | Feedback (1) | Filed Under [ .NET Goldstar ]


C# code for pulling data out of an IDataReader


I have a couple helper methods that I use all the time during my data access layer.  I figured I might as well post them and hopefully help others out.

I use the code from this article to pull my field names, that way I can build code like this:

public override IEntity PopulateFromOpenIDataReader(IDataReader dr)
{
    const int ID = 0;
    const int NAME = 1;
    const int COMMENT = 2;
    const int ADDRESS1 = 3;
    const int ADDRESS2 = 4;

    Doctor rv = new Doctor();

    rv.ID = (int)DataValidation.GetValueFromDR(dr, ID, 0);
    rv.StopName = DataValidation.GetValueFromDR(dr, NAME);
    rv.Comment = DataValidation.GetValueFromDR(dr, COMMENT);
    rv.Address.Address1 = DataValidation.GetValueFromDR(dr, ADDRESS1);
    rv.Address.Address2 = DataValidation.GetValueFromDR(dr,ADDRESS2);
    return rv;
}
 

The article with the DataValidation class code is here.

 

Technorati tags: , , ,

posted @ Thursday, May 03, 2007 1:11 PM | Feedback (0) | Filed Under [ .NET ]


OO Question


Let's say I have a base class that requires inheriting classes to implement a specific interface.  Is there a keyword or attribute I can put on my base class to tell inheriting classes that they must implement a specific interface? Or do I have to implement the interface in my base class, then also implement the interface in inheriting classes and override the base implementation?

Basically, I want to know if there is a cleaner way of accomplishing this

    public interface ICar
    {
        void UnlockCar();
        void StartCar();
        void Move();
    }
    public abstract class BaseCar : ICar
    {
        public void DriveAway()
        {
            //Will call the methods from
            //the inheriting class
            UnlockCar();
            StartCar();
            Move();
        }
        public virtual void UnlockCar() {}
        public virtual void StartCar(){}
        public virtual void Move() {}

    }

    public class OldCar : BaseCar, ICar
    {
        public override void UnlockCar()
        {
            Key.PutInDoor();
            Key.Turn();
        }

        public override void StartCar()
        {
            Key.PutInIgnition();
            Key.Turn();
        }

        public override void Move()
        {
            Clutch.Press();
            GearShaft.PutInFirst();
            Clutch.ReleaseSlowlyWhilePressingGas();
        }

    }

    public class NewCar : BaseCar, ICar
    {
        public override void UnlockCar()
        {
            Remote.PressUnlock();
        }

        public override void StartCar()
        {
            Key.PutInIgnition();
            Key.Turn();
        }

        public override void Move()
        {
            Brake.Press();
            GearShaft.PutInDrive();
            Brake.Release();
            Gas.Press();
        }
    }

    public class Consumer
    {
        public void MoveCars()
        {
            new OldCar().DriveAway();
            new NewCar().DriveAway();
        }
    }

posted @ Wednesday, May 02, 2007 11:24 AM | Feedback (4) | Filed Under [ .NET ]


How to get a new PPC6700


If you are tired of having your PPC-6700 set up just how you like it.  With your settings perfectly configured and all the applications loaded to make it an almost perfect replacement for your laptop, just simply run the update from Sprint's website.  It will fry your phone to paperweight status.

As an added bonus, you'll get to visit the friendly Sprint store and get to listen to their gorilla math logic for getting insurance.  Apparently, it makes fiscal sense to pay $7/month when a phone will have problems on average once a year.  Since getting a new phone cost me $35 and I've only had a problem like this once in the last 9 years, I see their point.

If that wasn't enough, you might get to carry around a beauty like this around for three to five business days:


DSC00555

 

All in all, they were really nice at the Sprint store and they are getting me a new phone.  It just sucks to have to pay $35 and have to reconfigure my phone when it wasn't my fault.  I've heard much worse horror stories from people with other providers.  Sprint has the best phones with the best features and the best network.  And they are planning on rolling out WiMax in 4Q of this year.

 

Technorati tags: , , , , , , ,

posted @ Tuesday, May 01, 2007 9:25 AM | Feedback (2) | Filed Under [ Mobile WiMAX ]