Random Thoughts of a Scatterbrain.
 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...

CAB, Model View Presenter, Passive View, and Humble Dialog

7/18/2007 10:24:03 AM (Eastern Daylight Time, UTC-04:00)

In trying to wrap my head around how solutions should be designed and componentized in SCSF/CAB, I've spent a bit of time trying to study up on Model View Controller (MVC) and Model View Presenter (MVP).

The packaged documentation, in my opinion, doesn't necessarily do a good job of covering these two topics and the variations of MVP that really make sense in CAB.

One of the best resources for discourse on these two topics is Martin Fowler's article on GUI Architectures, which provides a broad view of three of the most common underlying architectural choices for many of the GUIs that we work with today.

Of note is that Fowler's entry for MVP has been retired; instead, replaced with Passive View (PV) and Supervising Controller (SC).

What I've observed is that PV is more "aligned" with the design of the components in CAB than SC, which Fowler summarizes:

The separation advantage is that it pulls all the behavioral complexity away from the basic window itself, making it easier to understand. This advantage is offset by the fact that the controller is still closely coupled to its screen, needing a pretty intimate knowledge of the details of the screen. In which case there is a real question mark over whether it's worth the effort of making it a separate object.

In my opinion, since the CAB generated presenter isn't coupled with a concrete implementation of the view, PV is the way to go since this will allow a lower level of coupling with the concrete implementation of the view.  I went about this by adding interface methods to return Control (one could go as generic as Object as well) instances from the view which would then be rendered, wired, and databound by the presenter.  In other words, it's not really Model View Presenter as the documentation would have you believe.

Regardless, this allows a great deal of flexibility in the design of the module as a whole as the view can truly be replaced completely independently of the presenter since the presenter is only coupled with the interface class.  In addition, it allows for easy replacement of data visualization types using the adapter pattern to connect data to the control type (for example, having one adapter if the returned control is of type TreeView and another when the control is a DataGridView).

However, an even better description of the architectural intent of CAB modules is Humble Dialog, a pattern formalized by Michael Feathers.  What Feathers terms "smart object" is congruent to the presenter, which "pushes data onto the view class" through a view interface.  The view, of course, is the actual UserControl derived view class.  Now this leaves a key question: what is the place of the model in such a pattern?  Does it have a place?  With SCSF (but not necessarily with CAB when used with desktop applications), the classic sense of the model almost has no place in such an architecture; the model is but a dumb container for data.  It leaves you with what Fowler terms an Anemic Domain Model, an "anti-pattern":

The basic symptom of an Anemic Domain Model is that at first blush it looks like the real thing. There are objects, many named after the nouns in the domain space, and these objects are connected with the rich relationships and structure that true domain models have. The catch comes when you look at the behavior, and you realize that there is hardly any behavior on these objects, making them little more than bags of getters and setters. Indeed often these models come with design rules that say that you are not to put any domain logic in the the domain objects. Instead there are a set of service objects which capture all the domain logic. These services live on top of the domain model and use the domain model for data.

While Fowler views this pattern with disdain, I can't help but wonder whether it is the most natural choice for a smart client style application which should rely heavily on service layers to handle the data models.  Otherwise, it would seem that one would end up writing a great deal of domain objects which were nothing more than shells (well, perhaps this is still useful if complex service interactions are necessary) which make the calls through the service proxies.

 Tuesday, July 17, 2007

Tuesday Morning Thoughts

7/17/2007 10:50:01 AM (Eastern Daylight Time, UTC-04:00)

Some random stuff and some not so random stuff.

First, the Oral-B CrossAction Vitalizer is possibly the best damn (non-electric) toothbrush ever made.  It's comfy on the gums, it gets to the back teeth, and the handle is just right for control of pressure and angle.  The "soft" bristle isn't very soft at all, but I've found that it doesn't cause any pain or damage to my gums...it's just right.

Second, in reorganizing some of our code, I jumped headfirst into Microsoft's Smart Client Software Factory (SCSF).  While the verdict is far from conclusive, I have to say: I like it.  It implements several ideas I was tossing around in my head for a Windows Forms client but is obviously much, much more well developed and thought out.

I do find it annoying that it is somewhat difficult to visualize the relationships.  That is the one advantage to using an XML based object configuration system as opposed to the attribute based system used by the Composite Application UI Block that SCSF is built on: it's quite easy to wrap your head around the relationships and see how the pieces fit simply by reading the XML.  To be honest, it wouldn't be too terribly difficult to build similar (but certainly much less refined, given the amount of time I have) facilities with Spring utilizing the dependency injection, loosely coupled events, expression evaluation, and other components of Spring.

However, I think that the entire package, including the GAX pieces make this too compelling of a package to pass up.  There is surely a huge learning curve for the framework and library itself, but I think it will be made up for with the gain in development and deployment speed.

It's kind of cool that it also supports WPF modules.  I spent quite some time last night (up until 2 AM) trying to replicate some of the existing UI components that we have into WPF UIs.  I think I'm starting to "get it".  Not in the sense of why XAML is great for UI developers (I've always preferred declarative markup), but in the sense that I've kind of aligned myself with some of principles of XAML (i.e. layout, grids/tables, applying styles, backgrounds, etc. - which are of course slightly different than HTML) and I can now really appreciate how much easier it will be to create snazzy UIs in the future.

cab-hosted-wpf-UI.jpg

While I have Expresison Blend, I found it much more constructive to actually go into the raw XAML and write it by hand (well, not to mention that I find the UI hideous and unusable or perhaps I'm just way too Adobe-ized).  It was quite slow going at first, but once it clicked, it picked up very quickly.

Ultimately, however, I don't think that I can use WPF for our next release.  There seems to be some runtime instability with the current Visual Studio 2005 extensions (the November 2006 CTPs) to support WPF and WCF...I was only able to run my application once last night; subsequently, it would crash immediately.  The problem was only fixed by rebooting my machine.

But in any case, there are some great SCSF resources out there.  I would start from Cabpedia.com as CAB itself is really what presents the challenge in the Smart Client.  Cabpedia has a list of great resources which helped me at least grasp some of the conceptual ideas behind CAB.  In particular, a series of articles by Szymon Kobalczyk.

RSS 2.0 Atom 1.0 CDF