Random Thoughts of a Scatterbrain.
 Thursday, August 16, 2007

Book Review: Framework Design Guidelines

8/16/2007 4:30:48 PM (Eastern Daylight Time, UTC-04:00)

I originally came across a title Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries after perusing the documentation on the Subtext site.

For the most part, I had been following the guidelines outlined by Scott Bellware in his handy dandy style guide, but this text - FDG - takes it to another level and formalizes it in a way that it must be accepted by development teams since it was born from the source itself: the .NET Framework development teams.

I've reviewed it on Amazon, but here is the transcripted text:

I don't personally think that all developers will find this book useful. In fact, I have a feeling that some may find it highly useless and disruptive as it is abstract in a sense (one must apply the lessons to each library and scenario independently, taking into consideration many different aspects of usability and readability) and it does require some "retraining" of bad practices which have been long since ingrained due to years of usage.

But whether this book deserves a five star rating or a one star rating - whether this book is for you - can be answered by asking yourself the following question: are you obsessed with quality? Quality in the sense of creating a library that is:

- Easily reused by others, even first timers encountering the library or even first timers to .Net
- Well thought out with well designed classes
- Consistent within itself and consistent with the base libraries from Microsoft

The importance of the little things like naming classes, properties, methods, using one type of construct over another, using one type of accessor over another, etc. cannot be stressed enough in the overall picture of creating a library to a higher standard of quality, usability, and extensibility.

As Confucius is to have said:

"If names be not correct, language is not in accordance with the truth of things. If language be not in accordance with the truth of things, affairs cannot be carried on to success.

"When affairs cannot be carried on to success, proprieties and music do not flourish. When proprieties and music do not flourish, punishments will not be properly awarded. When punishments are not properly awarded, the people do not know how to move hand or foot.

"Therefore a superior man considers it necessary that the names he uses may be spoken appropriately, and also that what he speaks may be carried out appropriately. What the superior man requires is just that in his words there may be nothing incorrect."

As I wrote in an e-mail to my team, I think that digesting this book will lead to: higher quality public facing APIs for our customer development teams seeking to extend the functionality, increased readability and more consistency internally in our teams, increased usability and decreased maintenance costs for the support teams as well as new developers on our team, and of course, increased skill, knowledge, and competency as developers of each of the team members.

The title of this book is perhaps a bit misleading.  In reality, this book is applicable for anyone doing .Net development since it will lead to better quality code construction irregardless of whether you happen to be working on a "framework".  What I also like about the book is that the authors, architects, and various developers who worked on the .NET Framework admit error and inconsistency in some design and shows that this book is truly a work of the men in the trenches and intended for those of us who work on the front line of software development.

While the book does not delve into architecture or design, I think it still has value in enhancing the skill and mastery of any developer that takes the time to read it.  Definitely pick up this book if you are serious about becoming a better developer in the sense of being a more refined craftsman.

 Wednesday, August 15, 2007

Running Trac, Subversion, And Apache On Ports 80 And 443

8/15/2007 8:41:15 PM (Eastern Daylight Time, UTC-04:00)

If you are proxying Subversion through Apache, chances are you are probably using a non-default port since Apache won't start if you configure it use port 80 and 443 for SSL if you have IIS installed.  IIS uses socket pooling which binds port 80 and 443 on all IPs -- even ones not use by IIS -- to IIS.

To disable this behavior, you need the httpcfg.exe utility.  For Windows Server 2003, this can be found in the SP1 32-bit Support Tools download.  For Windows XP, the utility is available as part of the SP2 Support Tools download.

You can find a good overview of how to use this tool at neowin.net.

Some tips:

  • I didn't have luck running net stop http /y alone; I had to stop IIS first by running net stop iisadmin.
  • Assuming you have two or more IPs, the key is that you are actually telling IIS which IPs are okay to bind to.  If you are proxying Apache over IIS, you are likely (or should) use SSL.  This means that you have to make sure that you explicitly force IIS to bind to 80 and 443 for a specific IP and leave the other IP available for Apache.
 Tuesday, August 14, 2007

Random DevTools Entry: #014

8/14/2007 12:07:35 PM (Eastern Daylight Time, UTC-04:00)

Okay, so this isn't strictly a development tool, but Gantt Project has a pretty nifty, free, project management application.

With GanttProject you can break down your project into a tree of tasks and assign human resources that have to work on each task. You can also establish dependencies between tasks, like "this task can't start until this one is finished". GanttProject renders your project using two charts: Gantt chart for tasks and resource load chart for resources. You may print your charts, generate PDF and HTML reports, exchange data with Microsoft(R) Project(TM) and spreadsheet applications.

The site also mentions a good point with regards to Project:

  • Good (and growing!) set of basic features. This set is enough for most people (remember that 80% of MSProject customers use 20% of it's numerous features)
  • Easy learning. You don't need thick manuals to start working with GanttProject. If you are familiar with the notion of tasks, assignments and dependencies, you'll become an expert in GanttProject in a couple of hours.

Check it out if you're in the market for a free, simple, task based project management.

Normalizing And Denormalizing SharePoint Field Names

8/14/2007 11:45:29 AM (Eastern Daylight Time, UTC-04:00)

Frequently, when working with Office, SharePoint, and SharePoint web services, it is necessary to convert between the "normalized" (hex escaped string) version of a field name.

To that end, I found a useful JavaScript tool for normalizing strings into SharePoint's "static name" format.

In .Net, we can simplify this using Regex and Uri.

    private static readonly Regex specialCharactersPattern
        = new Regex("[\\[*($%&)<>!?\\/\"{}\\s+-='@~`#\\\\:;^\\]]", 
            RegexOptions.Compiled);

    private static readonly Regex encodedCharactersPattern
        = new Regex("_x00(\\d{2})_", RegexOptions.Compiled);

    /// <summary>
    /// Normalizes the name of the SharePoint property name.
    /// </summary>
    /// <param name="key">The "human readable" key/property name.</param>
    /// <returns>
    /// The string with hex representation in place of special ASCII
    /// characters.
    /// </returns>
    private static string NormalizeSharePointPropertyName(string key) {
        return specialCharactersPattern.Replace(key, ReplaceSpecialCharacter);
    }

    /// <summary>
    /// Custom match evaluator to replace special characters within the input
    /// string.
    /// </summary>
    /// <param name="match">The pattern match.</param>
    /// <returns>The formatted version of the string.</returns>
    private static string ReplaceSpecialCharacter(Match match) {
        string replacement = string.Format("_x00{0}_",
            Uri.HexEscape(match.Value[0]).TrimStart('%'));

        return replacement;
    }

    /// <summary>
    /// Denormalizes the name of the SharePoint property.
    /// </summary>
    /// <param name="key">The normalized key/property name (static name).</param>
    /// <returns>
    /// The denormalized form of the input string ("human readable"
    /// with hex patterns replaced).
    /// </returns>
    private static string DenormalizeSharePointPropertyName(string key) {
        return encodedCharactersPattern.Replace(key, DecodeSpecialCharacter);
    }

    /// <summary>
    /// Custom match evaluator to replace the hex characters with special characters.
    /// </summary>
    /// <param name="match">The pattern match.</param>
    /// <returns>The ASCII format of the special character encoded in hex.</returns>
    private static string DecodeSpecialCharacter(Match match) {
        int start = 0;

        string replacement =
            Convert.ToString(
                Uri.HexUnescape(Convert.ToString(match.Value[0]), ref start)
            );

        return replacement;
    }

Download the sample console project to test it out.

SharePointNormalizationConsole.zip (4.35 KB)

 Thursday, August 09, 2007

Commentary On Current Market Woes

8/9/2007 6:00:56 PM (Eastern Daylight Time, UTC-04:00)

This is probably the most sensible an informative bit of commentary on the current market conditions (DOW -387):

I love how 90% of farkers don't understand exactly what the crisis is right now.

It's not the fact that the housing bubble "burst". People aren't jumping out of skyscrapers because their house value went down by 5%.

The vast majority of the problem is that the credit market for certain types of bonds has tightened up, to the point that it's almost not even trading at this point. To those that are newbies, the bond market is roughly 10x the size of the stock market in terms of dollar value. It is huge. Bonds get traded back and forth every day, and billions upon billions of dollars worth.

What happened is that mortgage-backed securities are farked up. During the housing boom, lenders would give mortgages to people, then they would package them up and then sell a whole shiatload of mortgages to things like pension funds, hedge funds, mutual funds, etc. The lenders like this because they reduce their risk, and the funds like it because it's a reliable source of income, at least mortgage-backed securities are. Well, it turns out that the lenders were selling the funds investment grade mortgages, when in fact they were more like junk bonds; the people who got these mortgages not only faked their income, but in reality could only afford these mortgages under the best of conditions. Now that short-term interest rates have spiked up, many people have defaulted on these loans. More importantly however, the price of the mortgage-backed securities drop because their price is in part related to how reliable they are as an investment.

Now, many hedge funds invest in MBSs on margin, which really screws them up, because all of a sudden they owe a huge amount of money on worthless securities. This is why 2 Bearn Sterns hedge funds got screwed over and a 3rd one is in question. It's like owning stock in a gold mining company with a certain reported amount of gold, and then finding out that there really is no gold. The price will plummet, and if you bought that stock on margin, you will get a margin call.

The same thing happened with the French hedge fund that this article is talking about. What is worse, however, is that if the markets aren't trading, you can't tell how much the stock is worth, so the French stopped trading the funds until it can get better clarity as to how much their fund is worth.

The submitter's headline is misleading because the govt isn't injecting $12 billion, it's $12 billion more than they usually inject. They are always buying and selling bonds to create liquidity. This is what they mean by the US or Euro governments injecting funds into the bond market. They are going around buying bonds to create an artifical market because regular traders aren't buying them anymore. They are buying these bonds to create liquidity, so that traders will have confidence they can buy and sell bonds again, and once the market recovers they will turn around and start selling them back to replenish their reserves.

This is the real danger here. This MBS contagion has spread throughout the world because every one around the world has invested in US MBSs. We have no idea how bad this contagion has spread, but if this MBS problem takes down funds around the world, and the credit market really tanks and there is a flight to quality, making things like MBS fall even further, it could literally evaporated trillions dollars of peoples investments around the world.

From poster tstoneman.

I Hate Comcast

8/9/2007 2:52:02 PM (Eastern Daylight Time, UTC-04:00)

Over the past 4 years, I've been both a Comcast and Cablevision subscriber.  When I moved recently, I was "forced" into subscribing to Comcast due to whatever stupid regulations are in place limiting competition.

Let me list all the ways in which Comcast blows:

  1. Their customer service reps. are completely clueless.  It took me five call to three different people to figure out a stupid promotion that they were running that required you to be a customer already.  But clearly, on the ad, the terms and conditions state that it's available to new and existing customers.
  2. Their sales reps. are retards or just fuckups.  So to ensure that I got the exact package I wanted, just before I hung up with the rep., I specifically went over each line item to ensure that I was getting what I wanted.  Yet when the installation tech showed up - a day early, but an hour late - he didn't bring the right box!  I looked at the box to see if there were component cables and as I suspected, there weren't.  So I state "Hmmm...this doesn't look like an HD box" to which he responds "Yeah, I figured you wanted an HD box (gestures to TV)...those fuckups in sales...".  I check the order and indeed, not only was I not signed up for the package that I wanted, I was not signed up for HD either.
  3. Their customer service sucks.  So my wife goes to the local field office to tell them that they messed up their order.  Instead of offering for a tech to come out for free to claim the box and install an HD box, they hand her a new box and ask her to return the old one by Saturday.  That's quality service for ya' right there.
  4. The service sucks ass.  This deserves several sub-points:
    1. The digital voice comes with a shitty modem that has led to noticeably slower Internet performance (i.e. loading pages, sending files, etc).  You have no choice but to use this shitty modem.
    2. The digital cable is very unstable...many of the digital channels consistently lose integrity (blockiness, screen blacks out).
    3. The HD selection sucks.
    4. The fastest cable internet option costs $53 per month and it's only 8mbps downstream (and something like 1.5mbps up).  Contrast this with Cablevisions Optimum Online with Boost which offers 30mbps down/5mbps up for $44.95+$14.95.  Ho-lee shit.  There is no comparison.  To make matters worse, Boost comes with:
      1. A static IP (OH SCHNAPS!!)
      2. TOS allows outbound HTTP traffic over port 80!
      3. TOS allows outbound SMTP traffic over port 25!
  5. Comcast is expensive.  The Digital Preferred, which you need to get ESPN HD, costs $74/mo.  Plus, on top of the cable cost, you have to pay an extra $5 for HD channels and rental fee for the HD box.  Cablevision?  HD is included in all of the packages.  Plus, you can get most of the HD channels with the Silver Package @ $68/mo.

So in conclusion, Comcast sucks.  Cablevision has service to the zip code, but not to the street address...so what can I do but suffer :-(

 Monday, August 06, 2007

And I Thought My Setup Was Badass...

8/6/2007 3:07:20 PM (Eastern Daylight Time, UTC-04:00)

Excessive? Maybe.

Badass? Most definitely.

Now I'd be way more impressed if those monitors were 30-inchers.

 Friday, August 03, 2007

Random DevTools Entry: #013

8/3/2007 9:44:22 AM (Eastern Daylight Time, UTC-04:00)

Wow, it's been a looong time since I've added one of these.  I have a whole backlog of tools that I could add, but let's get to one of the important ones:

One of the really annoying things about Visual Studio is that renaming a project in the IDE doesn't change the name of the directory in the file system (or your source control).  Of course, updating the string in the code files is not so bad, but then you also have to go through all of the project and solution files to change all of those occurrences.

That's where the _REPLACE.EXE utility comes in.  Using a series of commands like the following:

_replace.exe "<old-string>" "<new-string>" /i /s /ext=.csproj
_replace.exe "<old-string>" "<new-string>" /i /s /ext=.sln
_replace.exe "<old-string>" "<new-string>" /i /s /ext=.cs
_replace.exe "<old-string>" "<new-string>" /i /s /ext=.resx
_replace.exe "<old-string>" "<new-string>" /i /s /ext=.config
_replace.exe "<old-string>" "<new-string>" /i /s /ext=.xml

You can pretty much replace most of the string names in your project by using that set of commands (and additional ones for any other file extensions).  What's cool is that you can also use the /t command line switch to do a dry run.

Very handy indeed.  Do keep in mind that you still have to go in and manually change the directory names but it's far more efficient than twiddling around with a text editor to replace the string in each of the project/solution files.

 Tuesday, July 31, 2007

Finding An Application Runtime By Extension

7/31/2007 12:38:53 PM (Eastern Daylight Time, UTC-04:00)

So a recent item that I've been tasked with is programmatically finding the application that is required to open/load a file of a given file extension.  One would think that this would be a straightforward task and quite easy to accomplish with .Net.

My first thought was to check the System.Environment namespace for any mappings of file extensions.  Nada.  My next instinct was to check System.Runtime.InteropServices to see if there was a chance that some object (maybe Marshal) had access to such a table.  No go.  I also stopped by Microsoft.Win32...nothing as well.

I did come across an interesting method in System.Drawing.Icon, ExtractAssociatedIcon() which would be useful if that was what I was after.  Unfortunately, I didn't find anything that would resemble this functionlity in System.IO.

So it would seem that for the time being, the only way that I can get at this data is to read registry keys.

What I've found is the following algorithm:

  1. Open HKEY_CLASSES_ROOT\<extension>\(Default). This gives us the class name that handles the file extension.
  2. Open HKEY_CLASSES_ROOT\<class-name>\CLSID\(Default). This gives us the GUID class ID of the application that handles the file extension.
  3. Open HKEY_CLASSES_ROOT\CLSID\<class-id>\InProcServer32|LocalServer32\(Default). This will yield the path to the executable which handles the file extension.

In some cases, it is enough to open the first key (the extension key) and you will find a subkey called OpenWithList with the first subkey being the name of the executable of the application (but this isn't always available).

I'm thinking there has to be a better way to do this programmatically, but I haven't come across it yet.

 Wednesday, July 18, 2007

Mindblowing Job Candidate Trawling...

7/18/2007 3:20:24 PM (Eastern Daylight Time, UTC-04:00)

The following are the contents of an actual email that I received this afternoon:

Hi cchen

I have a very hot Java Developer rek with a direct-client in Manhattan. Please send me candidates with rates and contact-numbers.

Interviews this week.

Thanks
-Priya M.

I would be shocked if Priya lands any candidate this year.

Let's dissect all of the ways that this email is completely ineffective:

  1. I am a .Net developer.  I know Java and worked with it for 4 years on college, but I have not worked with it in any sort of significant capacity since then.  Assuming this email was generated based on my profile on either Dice or Monster, you'd think that the recruiter would attempt to filter the candidates...
  2. "Hi cchen"?  Why am I being addressed by my email account name?  I'm pretty sure that I have my name listed on Dice and Monster.  If this were to have come from some third party database somehow, wouldn't it make sense to just use something like "Good afternnon,..."?
  3. "rek"?  Take some time and type out the extra keystrokes and spell it out.  A little professionalism goes a long way.
  4. No.  I am not doing your job for you.

Contrast this with another email from a Bradley G.:

Dear Applicant,

My name is Bradley and I'm an IT recruiter at [XYZ]Technologies Corporation. Our records show that you are an experienced IT professional with experience in .NET. This experience is relevant to one of my current openings.

The opening requires ASP in addition to the above skills.

It is located in Pittsburgh, PA.

If you are qualified, available, interested, planning to make a change, or know of a friend who might have the required qualifications and interest, even if we have spoken recently about a different position. You may also send me an e-mail with a copy of your current resume. If you do respond via e-mail please include a daytime phone number so I can reach you.  In considering candidates, time is of the essence, so please respond ASAP.  Thank you.

Sincerely yours,
Bradley G.

If you are not currently seeking employment, or if you would prefer I contact you at some later date, please indicate your date of availability so that I may honor your request. In any event, I respectfully recommend you continue to avail yourself to the employment options and job market information we provide with our e-mail notices.

Much more professional and much more likely to actually attract a candidate, but it still gets a few items wrong:

  1. I did not apply for any job.  It would have been better to use use a simple greeting like "Good afternoon" or "Greetings" or perhaps even something creative like "Hello from IT land!"
  2. I would have added "please responsd ASAP"...seems like a bad sales pitch.

Just some random afternoon ranting...

RSS 2.0 Atom 1.0 CDF