# Thursday, February 12, 2009

Quick background: I used to hate Microsoft and love Linux.  Now, and for the last 9+ years, I have made a living almost exclusively as a software developer on the Microsoft development platform.

Every now and then, I check back in with the non-.NET world to see how things are progressing. (I actually have a decent amount of first hand experience with Java and Perl.  I don't really have first hand experience with Ruby or Python or many of the other flavors currently getting a lot of press.)

There is still a lot of ignorance, which exists everywhere.  There is a lot of Microsoft hate and Sun hate and even some Ruby on Rails hate.

Here's the thing:

If you are given a set of well written business requirements, and you are a competent developer on the relevant platform, you can bang out a relatively easily maintained solution on various technology platforms without much problem.

However, if you are on a team of incompetent people, you will likely fail regardless of the technology platform.

If the business requirements are not written well, you will likely fail regardless of the technology platform.

So, the question in my mind is: how much of an obstacle to project success is the technology platform compared to the people and the requirements?  I think the answer is "not much".

So, why is so much time wasted with the angst and religious discussions about technology platforms?  I would rather see developers do the following with their time:

1) choose jobs with good people
2) learn to hire good people
3) learn how the business (of your customers) works so you aren't so dependent on requirements written (almost exclusively) by people who don't understand the technology platform being used to implement the solution

In my humble opinion, developers spend way too much time debating things (like technology platforms) that have minimal impact on project success.

I guess it should go without saying, but moving toward project success is pretty high on the list of goals for almost anyone, anywhere.  The technology platform of choice has very little impact on project success.

So, how did I choose a technology platform for me personally?  I made a bet.  I gambled.  I guessed that expertise in .NET would translate best into an income stream.  In the end, I may be horribly wrong, but so far it's working out okay for me.  As long as I/you can feed my/your family, any technology platform of choice is good enough.

Thursday, February 12, 2009 9:22:30 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, September 18, 2008

I did not attend the Business of Software 2008 Conference this year, but I spent some time tracking down write-ups done by people who did.

There is a Business of Software 2008 Wiki with some notes (and hopefully more to come?).

Cary Millsap wrote up some notes.

Steve Jones wrote up some notes (and there may be more still coming).

Cliff McCollum wrote up some notes (and it appears there is more coming).  I just linked to his business tag, so that link will not necessarily be as useful a month or so from now.

That's what I was able to find in a few minutes of googling.  There is probably more out there.

I came close to going this year, but cost and timing weren't great for me.  I'll probably consider attending this conference next year.

Thursday, September 18, 2008 7:27:54 PM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, September 17, 2008

TheLadders.com is a job website for $100k+ jobs:

http://www.theladders.com/

They apparently don't understand how to store multiple versions of a resume in a database though.  You can have one resume that you either type by hand or upload (and they will parse it... poorly).  If you hand edit the resume either before or after uploading, it gets stored.  However, if for some reason you upload the resume again for any reason, all the hand editing (except the Professional Overview section) is lost.

I chose not to upload my resume as I didn't want to waste a lot of time fixing whatever mess their parser made.  I spent hours hand editing my resume into their custom user interface, which is honestly not too great.  When recruiters see your resume, it's actually generated from the data in their database into a Microsoft Word document that looks semi-horrible (my two page resume became four pages with major white space and formatting issues).

I then went to submit my resume for their "free resume critique" (assuming you are a paying customer, which you pretty much have to be to get any value from the website).  If offered me the option of using what I hand edited or uploading a Microsoft Word document.  I thought my two page, nicely formatted resume would do better in a resume critique then their ugly four page thing, so I uploaded a Word version.  It did not take long to figure out what I stated above: that upload deleted all the data I hand entered and replaced it with their parsed garbage.  Multiple hours of work lost because I was tricked into believing that they might have a clue on how important it is to treat user entered data with high regard and not delete it without the user's knowledge.

So, I clicked their "Live Chat" button to talk to a support representative where I learned that the only thing they could restore was the Professional Overview section.  The support person was pleasant, but evasive: she appears to have had this conversation multiple times before.  I was not pleased.  She offered two additional weeks on my monthly subscription.  I said I honestly wasn't getting much, if any, value from TheLadders and said I'd rather cancel my subscription and get a refund, which she did without a hiccup.

I've been using web applications for a long time and I honestly can't remember having a website delete my data without asking me first, yet now it's happened to me twice in one day by two websites that should have known better.  Users beware.

Wednesday, September 17, 2008 9:48:27 PM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

Stack Overflow is a new Q&A website for developers, which is still in beta.  You can read more about it here:

http://www.joelonsoftware.com/items/2008/09/15.html

The URL to access Stack Overflow is here:

http://stackoverflow.com/

I love the idea/theory/vision behind this.  I have been reading Joel Spolsky and Jeff Atwood's blogs for years and I really enjoy and respect them.

The execution of the idea leaves a lot to be desired.  My expectations were probably way too high.  Joel and Jeff blog extensively about usability, yet the usability of Stack Overflow drives me crazy.

Here is specific feedback on what I would like to see changed with the implementation of Stack Overflow:

Let's start at the beginning:  Login.  If you go to login to Stackoverflow (login is optional, but required for the vast majority of the features of the web site), you run into something called OpenID.  For some people OpenID is probably a non-issue.  For me, it is an issue.  You can Google OpenID and read more about it, I'm not going to try to describe it.  Here are my issues with OpenID:

1) I immediately have to make a hard choice:  Do I trust some third party with my OpenID information or do I roll my own?  I don't like either option at all.  Rolling your own OpenID is non-trivial and under-documented.  I don't have any trust for any of the third party OpenID providers.  So, I of course threw up my hands and chose the path of least resistance: I just arbitrarily chose an OpenID provider and I pray it doesn't hurt me later.  I'm still upset about this.
2) I have to read extensively to understand what OpenID is.  Honestly, I don't care what it is and I don't care for it.  It's solving a problem I don't have now and I don't foresee ever having.  Why does Stack Overflow force me down this path?
3) I now have a really long, difficult to remember, user name.

Okay, that's a pretty horrible way to start off, but I'm now logged in.

I find a question I like, so I try to upvote it.  Oh, I can't do that until I have 15 reputation.  Earning reputation is either really easy or really hard, depending how good you are at that "mini-game".  Honestly, I don't care to play the mini-game.  So my ability to contribute to StackOverflow is limited, I can live with that.  Usage of the site over time will eventually unlock most of the reputation based features automatically as long as you are logged in while using the site.

So, I'm looking at questions and answers and I see these little bronze and silver badges by people's names.  I wonder what that is about.  Well, unless you happen to click on the badges button at the top of the page, it's actually fairly difficult to find out.  Search is unhelpful.  The official FAQ is unhelpful.  The unofficial FAQ is unhelpful.  This is the best part: You are not supposed to ask questions on StackOverflow about how to use StackOverflow.  Seriously.

Okay, so the usability leaves a lot to be desired so far.  I don't think my "new user" experience is so different from other people, but that's how I've been made to feel so far.

So, if you have a question about how to use StackOverflow, what are you supposed to do?  Use Uservoice:

http://stackoverflow.uservoice.com/

What is uservoice?  It's a third party feedback web application.  The usability of user voice is much, much worse than Stack Overflow itself.  You get dumped on a webpage with very little clue where you landed, why you landed there, or what you are supposed to do.

Let's go through the exercise of trying to figure out what the badges by people's names mean here.  I type in "badge" in the "I suggest you..." box.  I get 5 matches, none of which look like what I want.  So, at this point I guess I should "create new idea".  I get a tiny little popup box to type in.  I can't edit or delete it once I submit it.  I can't comment on it unless I login.  Comments can't be longer than 400 characters.  When I try to login to UserVoice, I can't use my StackOverflow (aka OpenID) credentials.  If I need to include my StackOverflow user name in my Uservoice comment, I need to type it out as the two systems aren't really integrated with each other (although you might get the impression that they are integrated with each other due to the fact that StackOverflow is displayed much more prominately on the UserVoice site than UserVoice is).

At this point, I'm mostly hate the user experience.  Let's look at some of the other comments on UserVoice about the user experience:

Here's a problem that new users are having that got an admin response that I think is dismissive:

http://stackoverflow.uservoice.com/pages/general/suggestions/25645

Here's what I would agree is a very valid point about the FAQ confusion (in fact, I would criticize the FAQ situation much more heavily):

http://stackoverflow.uservoice.com/pages/general/suggestions/26292

Here's a "feature" that I hate, but has been declined by the administrators as not going to be fixed:

http://stackoverflow.uservoice.com/pages/general/suggestions/24812

Users hate when they spend time entering data into your system and it disappears with zero indication why.  That is a horrible way to treat users.

In general, the tone of admin responses I see on User Voice is horrible and makes me not want to contribute there.

--

As a new user I posted a question on StackOverflow about what badges were and the next day that question disappeared, so I asked another question which will likely also disappear.  While this link remains valid, you can read more of the details of my non-wonderful StackOverflow experience:

http://stackoverflow.com/questions/82208/yesterday-i-posted-a-question-and-now-its-gone-where-did-it-go-how-do-i-view-it

Right now, I have to say "thumbs way down".  I'm pretty upset with how I was treated as a new user and I'm not sure if I should give the site another chance if/when it moves out of beta.  Maybe the site will take off and everyone will love it and I won't have a choice.

--

Updated 08/22/2009: Why I'm Using Stack Overflow

Wednesday, September 17, 2008 4:59:24 PM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, August 19, 2008

What is the difference between Visual Studio 2008 Standard and Visual Studio 2008 Professional?

Microsoft has provided multiple answers to this question:

(1)  This answer is quick and high level:

http://msdn.microsoft.com/en-gb/vs2008/products/bb980920.aspx

(2) This answer is less quick and slightly more detailed:

http://msdn.microsoft.com/en-us/library/zcbsd3cz(VS.80).aspx

(3) This answer is very detailed.  It comes in two flavors:

Web: http://msdn.microsoft.com/en-us/vs2008/products/cc149003.aspx

Downloadable: http://www.microsoft.com/downloads/details.aspx?FamilyID=727bcfb0-b575-47ab-9fd8-4ee067bb3a37&DisplayLang=en

 

Tuesday, August 19, 2008 1:22:32 PM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Saturday, March 01, 2008

When I went to install Microsoft Visual Studio 2005 Service Pack 1 on Windows Server 2003 I had a lot of unexpected trouble.

Windows Update gave me this obscure error code:

Error Code: 0x64C

So, I did some googling and landed on this very helpful web page:

Installing Visual Studio 2005 SP1

The main key was to look into the Event Log (how often I forget) and see this error:

---
Product: Microsoft Visual Studio 2005 Premier Partner Edition - ENU -- Error 1718.File C:\WINDOWS\Installer\66b5f.msp did not pass the digital signature check. For more information about a possible resolution for this problem, see http://go.microsoft.com/fwlink/?LinkId=73863.
---

I'm not even sure what "Premier Partner Edition" is.  It seems like I have that edition, plus the normal professional edition of VS 2005 installed.  Anyway, that helpful URL points to KB925336.  That knowledge base article points to a hotfix for Windows Server 2003, which is apparently required before installing large updates (and VS2K5 SP1 indeed appears to be large).

I did dig up my original installation media and did have that in my CD drive when I eventually successfully got the service pack to install, but I'm pretty confident it was the hotfix that got everything to work and I probably didn't need the CD.

It did take at least 20 minutes for the update to install (not including download time), so be patient.

Saturday, March 01, 2008 4:26:37 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, July 27, 2006

Every client I have done consulting at, without exception (so far), has done exception handling incorrectly in .NET.

This should not be too surprising given that people in VB6 and C++ rarely did exception handling right either.

In .NET (and Java), there are just a few things you have to remember (compared to VB6/C++) to do exception handling correctly.  Yet in ~5 years of looking for these simple rules, I have not yet found them (I discovered them the hard way, by maintaining production code that did exception handling incorrectly).

Here is my attempt at documenting good (and pragmatic) exception handling practices.  (Microsoft's attempt is here: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconBestPracticesForHandlingExceptions.asp)

These examples are specifically for VB.NET, but they basically apply in the same way to Java and C#.

How not to do it:

1)

On Error Resume Next

What you are doing:  You are ignoring *every* error and pretending it never happened and continuing execution.
Why that is bad:     Errors happen for a reason.  If you aren't even checking to see what error happened, how do you know you can safely continue to execute?  Continuing execution after an error occurred can easily lead to file or database corruption among other problems.


2)

Try
  ... code here ...
Catch
End Try

What you are doing:  You are ignoring *every* error and pretending it never happened and continuing execution.
Why that is bad:     Errors happen for a reason.  If you aren't even checking to see what error happened, how do you know you can safely continue to execute?  Continuing execution after an error occurred can easily lead to file or database corruption among other problems.


3)

Try
  ... code here ...
Catch exception As Exception
End Try

What you are doing:  You are ignoring *every* .NET Exception and pretending it never happened and continuing execution.
Why that is bad:     Errors happen for a reason.  If you aren't even checking to see what error happened, how do you know you can safely continue to execute?  Continuing execution after an error occurred can easily lead to file or database corruption among other problems.

4)

Try
  ... code here ...
Catch exception As Exception
  Throw exception
End Try

What you are doing:  You are resetting the stack trace for the error.
Why that is bad:     A normal stack trace will show the exact line the error originated from.  In this scenario, the stack trace will instead point the Throw line as the origin of the error.

--

Unless you are at the absolute top of the stack (i.e. the main method or a global exception handler), you never want to catch exceptions of type "Exception".  You should only be catching Exception classes that are below Exception in the hierarchy, and even more strongly, the leaf nodes of the Exception class hierarchy.


How to do exception handling properly:


1)

Really, try/catch is better than On Error GoTo, but this example is more for VB6 programmers who don't have try/catch.

On Error GoTo <ExceptionHandler>

You need to do all of the following in the Exception Handler:
(a) Close any open resources (database connections, etc.)
(b) Check the error/error code
(c) Check the line that the error occured on
(d) Put the error (message and stack trace with line numbers) somewhere so someone can see it (to the screen, to a log file, to a database, etc.)
(e) Take appropriate action (i.e. return an error code from the current function, exit the application, etc.)

2)

Try
  ... code here ...
Catch exception As SqlException
  Log(exception.ToString, selectStatement)
  Throw
End Try

Why is this better:
You are catching a specific exception class (SqlException) instead of something higher level like Exception.
You are logging the exception to a file, database, e-mail, etc. so a support person can log a defect for development to look at.
You are logging the database SELECT statement that was in use at the time the exception occurred.
You are rethrowing the exception as is so the stack trace will remain intact.

3)

Try
  ... code here ...
Catch innerException As SqlException
  Log(innerException.ToString)
  Throw New CustomException("SQL Statement [" & selectStatement & "]", innerException)
End Try

Why is this better:
You are catching a specific exception class (SqlException) instead of something higher level like Exception.
You are logging the exception to a file, database, e-mail, etc. so a support person can log a defect for development to look at.
You are throwing a custom exception that the calling method may be able to deal with easier/more successfully than a SqlException.
You are improving the information available in the exception.
You are including the innerException so that no information is lost on the new custom throw.

--

How do deal with third party event driven code:

If you are using badly behaved third party event driven code, it will sometimes throw away useful exception information.

For example, if you are handling/overriding events thrown by third party code, and an exception occurs in your code, that exception should go into the third party code and then make it back into your code that originally called the third party code.  Instead, the third party code may throw away the exception (because they have bad exception handling as described above).

In that case, before you leave your event handler, you need to catch every exception and log it so it doesn't get completely lost.  You should rethrow it, just in case the third party exception handling code is eventually fixed and they propagate the exception properly in the future.

Try
  ... code here ...
Catch innerException As Exception
  LogToFile("innerException [" & innerException.ToString() & "]")
  Throw New BizException("Exception in event handler for <third party package> Code", innerException)
End Try

--

A stack trace is a very important debugging tool.  If exceptions are not handled properly, stack traces get lost or mangled, making debugging much, much harder.

Here are some code samples with accompanying stack traces:

1)

Here is a fairly simple example that calls a function which causes an exception to be thrown.

This example has no try/catch block in the function, which is normal default behavior.  The try/catch block in the Main method is just so we can view the exception before the application closes and isn't necessary/useful for any other purpose.

--
Module Module1
    Sub Main()
        Try
            Dim age As Integer
            Dim ageAsString As String = "a1234"

            age = ConvertStringAgeToInteger(ageAsString)
        Catch exception As Exception
            System.Diagnostics.Debug.WriteLine(exception.ToString)
        End Try
    End Sub

    Function ConvertStringAgeToInteger(ByVal ageAsString As String) As Integer
        Dim age As Integer

        age = CInt(ageAsString)

        Return age
    End Function
End Module
--

Here is the associated stack trace.  It's pretty basic.  The DoubleType.Parse method threw a FormatException, which was then wrapped and rethrown in the IntegerType.FromString method by an InvalidCastException.  We don't have the line number in the stack trace for the Microsoft.VisualBasic component, but we do have the proper line numbers for our code.  Line 16 is the call to CInt.  Line 7 is the call to ConvertStringAgeToInteger.
--
System.InvalidCastException: Cast from string "a1234" to type 'Integer' is not valid. ---> System.FormatException: Input string was not in a correct format.
   at Microsoft.VisualBasic.CompilerServices.DoubleType.Parse(String Value, NumberFormatInfo NumberFormat)
   at Microsoft.VisualBasic.CompilerServices.DoubleType.Parse(String Value)
   at Microsoft.VisualBasic.CompilerServices.IntegerType.FromString(String Value)
   --- End of inner exception stack trace ---
   at Microsoft.VisualBasic.CompilerServices.IntegerType.FromString(String Value)
   at ExceptionHandlingSampleCode.Module1.ConvertStringAgeToInteger(String ageAsString) in C:\mmaddox\dev\Prototype\ExceptionHandlingSampleCode\Module1.vb:line 16
   at ExceptionHandlingSampleCode.Module1.Main() in C:\mmaddox\dev\Prototype\ExceptionHandlingSampleCode\Module1.vb:line 7
--

2)

We will now modify the above example to add some bad practices and see how the stack trace changes.
--
Module Module1
    Sub Main()
        Try
            Dim age As Integer
            Dim ageAsString As String = "a1234"

            age = ConvertStringAgeToInteger(ageAsString)
        Catch exception As Exception
            System.Diagnostics.Debug.WriteLine(exception.ToString)
        End Try
    End Sub

    Function ConvertStringAgeToInteger(ByVal ageAsString As String) As Integer
        Dim age As Integer

        Try
            age = CInt(ageAsString)
        Catch

        End Try
        Return age
    End Function
End Module
--

There is no output, we have completely ignored/squelched/destroyed the error and error information.  The age variable was never set as expected, but we have no way of knowing that.

3)

This is basically the same as above, but we will no longer catch non-.NET exceptions (that is the difference between "Catch" and "Catch exception As Exception".
--
Module Module1
    Sub Main()
        Try
            Dim age As Integer
            Dim ageAsString As String = "a1234"

            age = ConvertStringAgeToInteger(ageAsString)
        Catch exception As Exception
            System.Diagnostics.Debug.WriteLine(exception.ToString)
        End Try
    End Sub

    Function ConvertStringAgeToInteger(ByVal ageAsString As String) As Integer
        Dim age As Integer

        Try
            age = CInt(ageAsString)
        Catch exception As Exception

        End Try
        Return age
    End Function
End Module
--

Again, there is no output for the same reasons as above (the exception is a .NET exception, so it is caught and ignored).

4)

Now we will try to rethrow the exception incorrectly.
--
Module Module1
    Sub Main()
        Try
            Dim age As Integer
            Dim ageAsString As String = "a1234"

            age = ConvertStringAgeToInteger(ageAsString)
        Catch exception As Exception
            System.Diagnostics.Debug.WriteLine(exception.ToString)
        End Try
    End Sub

    Function ConvertStringAgeToInteger(ByVal ageAsString As String) As Integer
        Dim age As Integer

        Try
            age = CInt(ageAsString)
        Catch exception As Exception
            Throw exception
        End Try
        Return age
    End Function
End Module
--

Here is the output.  The big difference is that instead of line 16 (the call to CInt), the stack trace now shows line 19 (the Throw statement).  If the try block was 100 lines long, we would have no idea which line in the Try block caused the exception.
--
System.InvalidCastException: Cast from string "a1234" to type 'Integer' is not valid. ---> System.FormatException: Input string was not in a correct format.
   at Microsoft.VisualBasic.CompilerServices.DoubleType.Parse(String Value, NumberFormatInfo NumberFormat)
   at Microsoft.VisualBasic.CompilerServices.DoubleType.Parse(String Value)
   at Microsoft.VisualBasic.CompilerServices.IntegerType.FromString(String Value)
   --- End of inner exception stack trace ---
   at ExceptionHandlingSampleCode.Module1.ConvertStringAgeToInteger(String ageAsString) in C:\mmaddox\dev\Prototype\ExceptionHandlingSampleCode\Module1.vb:line 19
   at ExceptionHandlingSampleCode.Module1.Main() in C:\mmaddox\dev\Prototype\ExceptionHandlingSampleCode\Module1.vb:line 7
--

5)

So, now let's actually try to fix the code using a value of -1 to specify an invalid input value.
--
Module Module1
    Sub Main()
        Dim age As Integer

        Try
            Dim ageAsString As String = "a1234"

            age = ConvertStringAgeToInteger(ageAsString)
        Catch exception As Exception
            System.Diagnostics.Debug.WriteLine(exception.ToString)
        End Try

        System.Diagnostics.Debug.WriteLine("age is [" & age & "]")
    End Sub

    ' If this function returns -1, an error occured
    Function ConvertStringAgeToInteger(ByVal ageAsString As String) As Integer
        Dim age As Integer

        Try
            age = CInt(ageAsString)
        Catch exception As InvalidCastException
            age = -1
        End Try
        Return age
    End Function
End Module
--

Here is the output.  This is workable, but I'd rather see a very useful exception thrown than having to check for an error code (error codes are pretty much obsolete with .NET, unless you are doing COM Interop).  That brings us back to the very first sample code example, which I believe is more correct.  Don't catch exceptions unless you can actually do something useful with them!
--
age is [-1]
--

--

Here is an example of a case where I have found it useful to catch an exception.  In .NET 1.1, Integer.Parse will throw one of these three exceptions if the string is not parseable.  It would be quite a pain to check for these three exceptions every time we wanted to convert a string to an integer, but that is the proper way to do it (if you tried to catch a common parent exception, you might accidentally catch an OutOfMemoryException or some other exception that you should let bubble up to call stack).

An interesting note, in .NET 1.1, the Double class is the only one that has a "TryParse" method that will parse and return a boolean instead of an exception.  In .NET 2.0, they addressed this shortcoming.  The Integer class also has a TryParse method in .NET 2.0.
--
Module Module1
    Sub Main()
        Try
            If (IsValidInteger(Nothing)) Then
                System.Diagnostics.Debug.WriteLine("The Integer was valid!")
            End If
        Catch exception As Exception
            System.Diagnostics.Debug.WriteLine(exception.ToString)
        End Try
    End Sub

    Function IsValidInteger(ByVal integerAsString As String) As Boolean
        Try
            Integer.Parse(integerAsString)
        Catch argumentNullException As ArgumentNullException
            System.Diagnostics.Debug.WriteLine(argumentNullException.ToString)
            Return False
        Catch formatException As FormatException
            System.Diagnostics.Debug.WriteLine(formatException.ToString)
            Return False
        Catch overflowException As OverflowException
            System.Diagnostics.Debug.WriteLine(overflowException.ToString)
            Return False
        End Try
        Return True
    End Function
End Module
--

Thursday, July 27, 2006 12:48:50 PM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, November 09, 2005

One of my personal pet programming projects at one point in time was to create some kind of screen scraper of monster.com and other job websites so I could "download" all the current job postings and do things like:

1) Rank/Prioritize the job listings by personal appeal
2) Detect job listing duplicates between monster/dice/etc.
3) Keep track of which jobs I applied for and when
4) Automate running multiple queries with multiple terms in job site specific ways so I could detect new entries in my areas of interest (something an RSS feed would normally be used for)
5) Categorize jobs by factors that were important to me - Salary, Location, Consulting vs. Full-time, How qualified I thought I was, etc.

Everyone puts that much effort into their job search, right?  ;)

I did get something of an automated process for the worst bits with tons of manual intervention required such that I could do this and it worked wonderfully.  It was never anywhere close to automated enough to share with friends though.  However, screen scrapping different web sites is not fun, rewarding work and I eventually shelved the project (and I now find most of my contract work through recruiters who I've talked to in the past and never apply for jobs from web site job listings anymore).

I still think this is very cool though:

http://www.indeed.com/jsp/apiinfo.jsp

Indeed is yet another job search engine, except with one major difference (it may not be the only job search engine with this feature, but it's the only one I know of).  Indeed publishes a Web Services API which you can query directly that seems to return job listings from Monster, Dice, etc.  This would have made my pet project above a piece of cake to implement.  This is a very good sign of things to come in the web services world!

Now if someone would just publish a web service for stock price quotes (you know it's going to happen eventually).

Wednesday, November 09, 2005 2:13:21 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [2]  | 
# Tuesday, September 27, 2005

Scott Hanselman is great at evaluating all the little tools developers should be usingYesterday, he brought me to PureText.

While not the bane of my existence, the "Paste Special" feature is something I use *constantly*.  Unlike hotkey maven Scott, I was doing it with mouse clicks, which is even more painful.  Windows-V to "paste special" with one click is *exactly* the most important feature I've wanted added to all Microsoft software.  Thank you Steve Miller!!!

Tuesday, September 27, 2005 3:12:36 PM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, August 11, 2005

ASP.NET Simplicity -- When Is Too Much Simplicity a Bad Thing

This is a good post to read, plus all the comments.  Many developers have real concerns about ASP.NET 2.0 and the direction it's taken.  ASP.NET 1.X is a very good product.  I'm really not so sure about ASP.NET 2.0.

I'd like to see Microsoft step up to the plate here and instead of saying it's "working as designed" say "we are listening to your feedback and we are going to slip the release date so we can do it right".

I've thought about trying to stick with ASP.NET 1.X, but there are just so many (too many?) obstacles.  I can't throw out all of Visual Studio 2005 just because I'm not happy with the breaking changes to ASP.NET 2.0.  I really like most of the VS 2005 non-ASP.NET 2.0 related changes.  I even like some of the ASP.NET 2.0 non-breaking changes.

I'm sure there are a lot of people watching to see what Microsoft does with this one.  Backward compatibility matters.

Thursday, August 11, 2005 11:52:43 PM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  |