Technical Interview Questions

flogging

Interviewing has been on a my mind, of late, as my company is in the middle of doing quite a bit of hiring.  Technical interviews for software developers are typically an odd affair, performed by technicians who aren’t quite sure of what they are doing upon unsuspecting job candidates who aren’t quite sure of what they are in for.

Part of the difficulty is the gap between hiring managers, who are cognizant of the fact that they are not in position to evaluate the skills of a given candidate, and the in-house developers, who are unsure of what they are supposed to be looking for.  Is the goal of a technical interview to verify that the interviewee has the skills she claims to possess on her resume?  Is it to rate the candidate against some ideal notion of what a software developer ought to be?  Is it to connect with a developer on a personal level, thus assuring through a brief encounter that the candidate is someone one will want to work with for the next several years?  Or is it merely to pass the time, in the middle of more pressing work, in order to have a little sport and give job candidates a hard time?

It would, of course, help if the hiring manager were able to give detailed information about the kind of job that is being filled, the job level, perhaps the pay range — but more often than not, all he has to work with is an authorization to hire “a developer”, and he has been tasked with finding the best that can be got within limiting financial constraints.  So again, the onus is upon the developer-cum-interviewer to determine his own goals for this hiring adventure.

Imagine yourself as the technician who has suddenly been handed a copy of a resume and told that there is a candidate waiting in the meeting room.  As you approach the door of the meeting room, hanging slightly ajar, you consider what you will ask of him.  You gain a few more minutes to think this over as you shake hands with the candidate, exchange pleasantries, apologize for not having had time to review his resume and look blankly down at the sheet of buzzwords and dates on the table before you.

Had you more time to prepare in advance, you might have gone to sites such as Ayenda’s blog, or techinterviews.com, and picked up some good questions to ask.  On the other hand, the value of these questions is debatable, as it may not be clear that these questions are necessarily a good indicator that the interviewee had actually been doing anything at his last job.  He may have been spending his time browsing these very same sites and preparing his answers by rote.  It is also not clear that understanding these high-level concepts will necessarily make the interviewee good in the role he will eventually be placed in, if hired. 

Is understanding how to compile a .NET application with a command line tool necessarily useful in every (or any) real world business development task?  Does knowing how to talk about the observer pattern make him a good candidate for work that does not really involve developing monumental code libraries?  On the other hand, such questions are perhaps a good gauge of the candidate’s level of preparation for the interview, and can be as useful as checking the candidate’s shoes for a good shine to determine how serious he is about the job and what level of commitment he has put into getting ready for it.  And someone who prepares well for an interview will, arguably, also prepare well for his daily job.

You might also have gone to Joel Spolsky’s blog and read The Guerrilla Guide To Interviewing in order to discover that what you are looking for is someone who is smart and gets things done.  Which, come to think of it, is especially helpful if you are looking for superstar developers and have the money to pay them whatever they want.  With such a standard, you can easily distinguish between the people who make the cut and all the other maybe candidates.  On the other hand, in the real world, this may not be an option, and your objective may simply be to distinguish between the better maybe candidates and the less-good maybe candidates.  This task is made all the harder since you are interviewing someone who is already a bit nervous and, maybe, has not even been told, yet, what he will be doing in the job (look through computerjobs.com sometime to see how remarkably vague most job descriptions are) for which he is interviewing.

There are many guidelines available online giving advice on how to identify brilliant developers (but is this really such a difficult task?)  What there is a dearth of is information on how to identify merely good developers — the kind that the rest of us work with on a daily basis and may even be ourselves.  Since this is the real purpose of 99.9% of all technical interviews, to find a merely good candidate, following online advice about how to find great candidates may not be particularly useful, and in fact may even be counter-productive, inspiring a sense of inferiority and persecution in a job candidate that is really undeserved and probably unfair.

Perhaps a better guideline for finding candidates can be found not in how we ought to conduct interviews in an ideal world (with unlimited budgets and unlimited expectations), but in how technical interviews are actually conducted in the real world.  Having done my share of interviewing, watching others interview, and occasionally being interviewed myself, it seems to me that in the wild, technical interviews can be broken down into three distinct categories.

Let me, then, impart my experience, so that you may find the interview technique most appropriate to your needs, if you are on that particular side of the table, or, conversely, so that you may better envision what you are in for, should you happen to be on the other side of the table.  There are three typical styles of technical interviewing which I like to call: 1) Jump Through My Hoops, 2) Guess What I’m Thinking, and 3) Knock This Chip Off My Shoulder.

 

Jump Through My Hoops

tricks

Jump Through My Hoops is, of course, a technique popularized by Microsoft and later adopted by companies such as Google.  In its classical form, it requires an interviewer to throw his Birkenstock shod feet over the interview table and fire away with questions that have nothing remotely to do with programming.  Here are a few examples from the archives.  The questions often involve such mundane objects as manhole covers, toothbrushes and car transmissions, but you should feel free to add to this bestiary more philosophical archetypes such as married bachelors, morning stars and evening stars, Cicero and Tully,  the author of Waverly, and other priceless gems of the analytic school.  The objective, of course, is not to hire a good car mechanic or sanitation worker, but rather to hire someone with the innate skills to be a good car mechanic or sanitation worker should his IT role ever require it.

Over the years, technical interviewers have expanded on the JTMH with tasks such as writing out classes with pencil and paper, answering technical trivia, designing relational databases on a whiteboard, and plotting out a UML diagram with crayons.  In general, the more accessories required to complete this type of interview, the better.

Some variations of JTMH rise to the level of Jump Through My Fiery Hoops.  One version I was involved with required calling the candidate the day before the job interview and telling him to write a complete software application to specification, which would then be picked apart by a team of architects at the interview itself.  It was a bit of overkill for an entry-level position, but we learned what we needed to out of it.  The most famous JTMFH is what Joel Spolsky calls The Impossible Question, which entails asking a question with no correct answer, and requires the interviewer to frown and shake his head whenever the candidate makes any attempt to answer the question.  This particular test is also sometimes called the Kobayashi Maru, and is purportedly a good indicator of how a candidate will perform under pressure.

 

Guess What I’m Thinking

brain

Guess What I’m Thinking, or GWIT, is a more open ended interview technique.  It is often adopted by interviewers who find JTMH a bit too constricting.  The goal in GWIT is to get through an interview with the minimum amount of preparation possible.  It often takes the form, “I’m working on such-and-such a project and have run into such-and-such a problem.  How would you solve it?”  The technique is most effective when the job candidate is given very little information about either the purpose of the project or the nature of the problem.  This establishes for the interviewer a clear standard for a successful interview: if the candidate can solve in a few minutes a problem that the interviewer has been working on for weeks, then she obviously deserves the job.

A variation of GWIT which I have participated in requires showing a candidate a long printout and asking her, “What’s wrong with this code?”  The trick is to give the candidate the impression that there are many right answers to this question, when in fact there is only one, the one the interviewer is thinking of.  As the candidate attempts to triangulate on the problem with hopeful answers such as “This code won’t compile,” “There is a bracket missing here,” “There are no code comments,” and “Is there a page missing?” the interviewer can sagely reply “No, that’s not what I’m looking for,” “That’s not what I’m thinking of, “That’s not what I’m thinking of, either,” “Now you’re really cold” and so on.

This particular test is purportedly a good indicator of how a candidate will perform under pressure.

 

Knock This Chip Off My Shoulder

eveready

KTCOMS is an interviewing style often adopted by interviewers who not only lack the time and desire to prepare for the interview, but do not in fact have any time for the interview itself.  As the job candidate, you start off in a position of wasting the interviewer’s time, and must improve his opinion of you from there.

The interviewer is usually under a lot of pressure when he enters the interview room.  He has been working 80 hours a week to meet an impossible deadline his manager has set for him.  He is emotionally in a state of both intense technical competence over a narrow area, due to his life-less existence for the past few months, as well as great insecurity, as he has not been able to satisfy his management’s demands. 

While this interview technique superficially resembles JTMFH, it is actually quite distinct in that, while JTMFH seeks to match the candidate to abstract notions about what a developer ought to know, KTCOMS is grounded in what the interviewer already knows.  His interview style is, consequently, nothing less that a Nietzschean struggle for self-affirmation.  The interviewee is put in the position of having to prove herself superior to the interviewer or else suffer the consequences.

Should you, as the interviewer, want to prepare for KTCOMS, the best thing to do is to start looking up answers to obscure problems that you have encountered in your recent project, and which no normal developer would ever encounter.  These types of questions, along with an attitude that the job candidate should obviously already know the answers, is sure to fluster the interviewee. 

As the interviewee, your only goal is to submit to the superiority of the interviewer.  “Lie down” as soon as possible.  Should you feel any umbrage, or desire to actually compete with the interviewer on his own turf, you must crush this instinct.  Once you have submitted to the interviewer (in the wild, dogs generally accomplish this by lying down on the floor with their necks exposed, and the alpha male accepts the submissive gesture by laying its paw upon the submissive animal) he will do one of two things;  either he will accept your acquiescence, or he will continue to savage you mercilessly until someone comes in to pull him away.

This particular test is purportedly a good indicator of how a candidate will perform under pressure.

 

Conclusion

moderntimes

I hope you have found this survey of common interviewing techniques helpful.  While I have presented them as distinct styles of interviewing, this should certainly not discourage you from mixing-and-matching them as needed for your particular interview scenario.  The schematism I presented is not intended as prescriptive advice, but merely as a taxonomy of what is already to be found in most IT environments, from which you may draw as you require.  You may, in fact, already be practicing some of these techniques without even realizing it.

Gypsy Groove

sleeping

Why are gypsies commonly believed to be able to foretell the future?

This is the question that sets Pierce Moffett, the hero of John Crowley’s novel Aegypt, in search of the true origin of the Roma, and with it the true meaning of history.  In his novels about Moffett, Crowley unravels a world in which history not only can be broken into different periods (The Dark Ages, The Renaissance, The Enlightenment, et. al.), but in which the rules by which the world works shifts and ruptures between these eras. 

And there are in fact people who believe such things.  A friend once told me about a history professor of his who lectured on the prevalence of sightings of angels and spirits in Medieval and Renaissance literature, and questioned how so many people could believe such things.  His radical conclusion, which he believed irrefutable, was that such things must have once been real.

John Crowley himself is a skeptic on such matters, as people often are who play too much at pretending to believe.  At a certain point, one must choose either to cross the line into a possible madness, or draw back into a more definite epoche — a suspension of belief.

We, who have not stepped so deeply into these mysteries, are in a safer position to toy with possibilities, engaging in what Coleridge called the suspension of disbelief.  It is what allows us to understand and even share in Don Quixote’s delusions, without thereby succumbing to them ourselves.

When I lived in Prague a few years back, there were stories about a gypsy bar on the edge of the city where one could meet gypsy princes and sip absinthe, a concoction that is illegal in much of the developed world.  I never went of course, partly from a lack of courage, and partly out of a fear that confronting the thing itself would dispel for me the image I had already formed in my imagination of that magic place.

Over the years, I’ve privately enjoyed several fantasies about that bar.  In some of these, I drink the absinthe and am immediately transformed, through a sudden revelation, into a passionate artist who spends the rest of his life trying to paint something he cannot quite capture.  In others, I am accosted by a gypsy prince, and, defeating him in a bloody duel with knives, I leave with his gypsy bride.  In most, I simply am kidnapped by the gypsies while in the grips of an absinthe induced haze, and eventually learn their ways and join their tribe, traveling across Europe stealing from the rich and conning the gullible.

Such is my secret life, for what it is worth.  Inspired by this secret dream to be a gypsy, I have been listening to an album called Gypsy Groove, groove being the postpositional modifier that does in the 21st century what hooked-on did for us in the 20th.  The copywriting claims it is “a collection of Balkan beats, gypsy jams and other treats from the leaders of this vibrant music scene.”  I prefer the way my son (a natural poet, I believe) describes it: “it makes my ears sing and my butt dance.”  I am especially fond of the song Zsa Manca, by the Czech group !DelaDap.

According to Pierce Moffett, the gypsies are refugees from a time that no longer exists, from a country called, not Egypt, but rather its mythical homophone, Aegypt.  In order to explain this strange origin, Crowley builds a fictional story on top of a true story about how scholars in the Renaissance mistakenly projected the origins of certain texts, already ancient in their own time, to a pre-history even more ancient, and a provenance somewhere in the geographical Egypt.

If you don’t already know this story (either the false one or the real one), and you have the patience for it, here is John Crowley’s explanation of both, from Love & Sleep:

It was all true: there really had once been a country of wise priests whose magic worked, encoded in the picture-language of hieroglyphics.  That was what Pierce had learned in his recent researches.  It did lie far in the past, though not in the past of Egypt.  It had been constructed long after the actual Egypt had declined and been buried, its mouth stopped because its language could no longer be read.

And this magic Egypt really had been discovered or invented in Alexandria around the time of the Christianization of the Roman Empire, when a Greek-speaking theosophical cult had attributed some mystical writings of their own to ancient priests of an imaginary Egyptian past of temples and speaking statues, when the gods dwelt with men.   And then that imagined country really had disappeared again as those writings were lost in the course of the Christian centuries that followed.

And when they were rediscovered — during the Renaissance in Italy, along with an entire lost past — scholars believed them to be really as ancient as they purported to be.  And so a new Egypt, twice different from the original, had appeared: ancient source of knowledge, older than Moses, inspiring a wild syncretism of sun-worship, obelisks, pseudo-hieroglyphs, magic and semi-Christian mysticism, which may have powered that knowledge revolution called science, the same science that would eventually discredit imaginary Egypt and its magic.

And yet even when the real Egypt had come to light again, the tombs broken open and the language read, the other country had persisted, though becoming only a story, a story Pierce had come upon in his boyhood and later forgot, the country he had rediscovered in the City in the days of the great Parade, when he had set out to learn the hidden history of the universe: the story he was still inside of, it seemed, inescapably.

Aegypt.

Just this year, John Crowley finally published the fourth book in his Aegypt Quartet, bringing the series to a close.  It is called Endless Sleep.

Giornale Nuovo Stops Its Presses

gn

 

Giornale Nuovo, a blog written anonymously by someone calling himself Misteraitch, is coming to an end after five years.  Without any exaggeration, it has been one of the best things available on the net over that time, and Misteraitch’s  efforts will be sorely missed.

Giornale Nuovo falls into that strange category of erudite blogs in which the author takes a personal passion and draws one into it.  M.’s passion happens to be rare books, and in particular rare illustrated books.  Based in Italy, and later somewhere in Scandinavia, he would haunt the odd bookstores of Europe tracking down rumors of quaint and curious volumes of forgotten lore — so to speak — and once acquired, he would digest them through his scanner and publish them on his blog, pointing out the peculiarities of his acquisitions.  He is also an art lover, and was quite good at finding painters, sculptors, and installation artists that you had never heard of before but whom, after reading the blog, you would never forget.

And now, M. is hanging up his spurs.  Fortunately, he will be leaving the archives of his blog up for a while, giving readers a chance to catch up on his industriousness somewhat belatedly — I almost said posthumously.  M.’s main complaint, I take it, is exhaustion.  It takes much out of a person to continuously publish writing of this caliber, and no doubt M. was concerned that his output would eventually flag.  Going through the archives, however, I see little sign of this.  All the entries are consistently good.  Take, for instance, his contribution to our common knowledge with Curiosities of Literature, or his frequent entries on Emblem Books, or this one about Anthropomorphic Alphabets.  These I selected randomly, just to give you a taste of what I have been enjoying for many months.

M. is also rightly famous for his giveaways.  Every so often, he would decide that his bookshelves were too full, or his CD collection too disorganized, and he would simply list the overflow of books or music on his site, with charming descriptions, and then mail them, gratis, to the first person who showed any interest (one year I received Rachmaninov’s Vespers from him). 

Such generosity was not uncommon with M., and his entire site is, in fact, a five year act of generosity in which he artfully lay out his personal tastes for the world to view.  If you have never visited Giornale Nuovo before, then I heartily recommend that you take this opportunity to browse through its archives while it is still available.  It is a monument of the Internet not to be missed, and a rare example of how technology, rather than twisting the human soul, can actually make it soar.

Install Visual Studio 2008 beta without a DVD Burner

I had a weird problem with my DVD player, such that while I was able to burn the Visual Studio 2008 image successfully, I was not able to use it to install.  Instead, the DVD would just lock up my XP operating system.  So I resorted to my backup plan, which involved simply mounting the image as if it were a media device and running the install from there.

I was able to do this using free software provided by Microsoft called the XP Virtual CD Control Panel.  But first, a public service message: beta software such as Visual Studio 2008 should not be installed on a production machine since it is not supported.  Likewise, the Virtual CD Control Panel is unsupported, by which I mean if you have problems with this you can’t call Microsoft for help, and should be installed at your on risk.

With that out of the way, the Visual Studio 2008 (Orcas) beta image file can be downloaded here, while the Virtual CD software can be gotten here.  The Virtual CD download is a executable zip file, which you should unzip to an easily accessible location on your harddrive.  It includes the VCdControlTool executable, a readme file, and a file called VCdRom.sys.  Copy VCdRom.sys file to your system32\drivers directory.

VCdControlTool

  1. Run VCdControlTool.exe
  2. On the first run, the driver will not have been loaded yet, so click “Driver control”, click “Install Driver”, navigate to the %systemroot%\system32\drivers folder, select VCdRom.sys, and click Open. Click “Start”. Click OK.
  3. Click “Add Drive” to add a drive to the drive list. Ensure that the drive added is not a local drive. If it is, continue to click “Add Drive” until an unused drive letter is available.
  4. Select an unused drive letter from the drive list and click “Mount”.
    Navigate to the directory to which you downloaded the OrcasBeta2VSTSX1394647.img image file.   In your dialog window, change the “files of type” option to All files (“*”). Now you should be able to see the Visual Studio 2008 image file. 
  5. Select the image file and click “OK”.  (You can leave all the option check boxes unselected.)
  6. Return to your windows browser, where you should find the image file under Devices with Removable Storage.  Double click it to begin the install.

orcasinstall

Session Expired Monitor with ASP.NET AJAX

timeout

code download

Sessions are a way of preserving information on a web site between page hits, allowing the programmer to emulate a stateful application when, in fact, web pages are not really stateful.  They are also one of the banes of web development, since sessions eventually timeout when there is no interaction between the user and the web app for a prolonged period of time.  In ASP.NET, this period has a default of 20 minutes, which is really hardly enough time to pick up a donut, refill one’s coffee, and chat with fellow workers before returning to one’s computer.  What this often means is that the user, upon returning to their computer and continuing work after a 20 minute break will find that all of the data entry they have been doing has been lost.  Worse, strange errors will begin to appear in his web browser if the loss of a session is not handled gracefully. 

The most common workaround is to increase the session grace period, called the session timeout.  This is set in your web.config file, and typically looks like this (the timeout period is measured in minutes):

  <system.web>
    <sessionState
      mode="InProc"
      cookieless="false"
      timeout="20"
     />
  </system.web>

A second way of handling this is to add extra code to an app that keeps the session state alive even if the user isn’t doing anything.

A third, and the most common, way is to provide code that redirects a user to a “session expired” page if they try to interact with a web page for which the session has timed-out.  This can be a bit awkward, however, since it is a passive solution that can cause the user some dismay as they hit a submit key only to be taken to a completely unexpected page.

This post deals with an active approach to the same problem.  When the user’s session has expired, it will generate a popup message in the user’s browser window letting him know that he has been inactive for too long.  Additionally it can redirect the browser to a new page with a warning message letting him know what happened.  The user still loses all of his work, of course, but at least this way he knows what happened when he returns to his desk following his coffee break.

This solution uses three tricks.  One is the event model for Master Pages in ASP.NET:  whenever a Content Page is refreshed, its OnLoad event is called,  along with the OnLoad events of the Master Page and any user controls hosted by either the Content Page or the Master Page (the actual order of these events is 1. controls on the Master Page, 2. controls in the Content Page, 3. the Master Page and finally 4. the Content Page).

The second trick is the way ASP.NET Extensions Timer control gets reset.  This is done simply by setting the interval to a new value.  Every time the interval is set to a new value, or even the same value, the countdown on the timer begins again.

The third trick is that the session timeout one sets in the web.config file can be read programmatically simply by querying a property of the Session object.

Putting all of this together, one can build a web user control that simply sits on a Master Page and knows when the user session is ready to expire.  It resets itself to the full timeout period any time a Content Page is refreshed.  when the session expires, the user control can raise an informative message, redirect to another page, or, potentially, simply extend the session timeout (not covered here, but easy to do if you are interested).

A user control to monitor the session timeout is included in the code sample linked at the top of this post.  Here is how you can build your own.

Session Timeout Monitor Recipe:

Ingredients:

  • One Master Page
  • One User Control
  • An Update Panel
  • An ASP.NET Ajax Extensions Timer
  • A Panel control
  • A Button control

1. Create a new User Control in your project. 

2. Drop an Update Panel on the User Control and set its mode property to “Always”.

3. Add an Extensions Timer (not to be confused with the Futures TimerControl) to your project, dropping it in the Update Panel.  Name it TimerTimeout.

Normally, this configuration of the timer control and a conditional update panel is used to refresh a portion of a web page on a regular schedule, for instance in order to create a self-updating clock display.  In this case, however, the timer and update panel are used simply to trigger a notification that the session has expired. 

4. In the User Control’s code behind, add the following lines to the OnLoad event:

        protected void Page_Load(object sender, EventArgs e)
        {
            int milliseconds = 60000;
            TimerTimeout.Interval = Session.Timeout * milliseconds;
        }

This event will be called any time a content page is refreshed.  Whenever this happens, the code inside the event handler resets the AJAX Extensions Timer control to the full session lifespan as set in the web config file, in effect making the timeout for the Timer match the timeout for the session.

Since the Timer control’s Interval property is measured in milliseconds, while the session.Timeout is measured in minutes, a conversion factor of sixty thousand must be used to translate one time period into the other.

To finish this notifier, the Timer’s Tick event needs to be handled.  The Tick event gets called when the Timer’s Interval finally runs out.  In this implementation, the Tick event can either generate a popup message or cause a page redirect.

5. Place a Panel inside the Update Panel.  Set its Visible property to false.

6. Write a simple message inside the Update Panel, such as “Your session has expired.”

7. Drop a Button inside the Panel.  This Button will be used to allow the user to hide the popup message.

8. Add a public property to the User Control called SessionExpiredRedirect:

        private string _sessionExpiredRedirect;

        public string SessionExpiredRedirect
        {
            get { return _sessionExpiredRedirect; }
            set { _sessionExpiredRedirect = value; }
        }

This will be used to set the web page to which the Timer will redirect the user upon session timeout.  If no value is set, a popup message will appear, instead.

9. Handle the Timer’s Tick event:

        protected void TimerTimout_Tick(object sender, EventArgs e)
        {

            if (!string.IsNullOrEmpty(SessionExpiredRedirect))
            {
                if (SessionExpiredRedirect.IndexOf("~")==0)
                    Response.Redirect(
                        VirtualPathUtility.ToAppRelative(
                        SessionExpiredRedirect));
                else
                    Response.Redirect(SessionExpiredRedirect);
            }
            else
                this.PanelTimeout.Visible = true;
        }

This handler checks to see if a value has been set for the SessionExpiredRedirect property.  If not, it makes the Panel control inside the Update Panel visible.

10. To make the Panel control truly popup, set its CssClass property to “timeoutMessage”.  Add the following css style to the page.

<style type="text/css">
.timoutMessage
{
    position:absolute;
    top:100px;
    left:200px;
    background-color:#F5F7F8;
    border-style:groove;
    border-color:Navy;
    padding:15px;
}
</style>

11. Finally, compile this User Control and drag it on to the Master Page.  In design mode, the user control will display a misleading exception message.  Just ignore it.

12. Make sure the Master Page includes an ASP.NET AJAX Script Manager component.

This completes the recipe.  Any Content Page in this project will now automatically include the timeout monitor you have built.  Cookies are optional: this recipe will work with a session managed either with cookies or in cookieless mode.  It will only work if the session mode is InProc.

Garnish with buttered radishes.  Serve at room temperature.

(Code snippets formatted using manoli.net.)

C Sharp’s Double Question Mark Operator Recipe (??)

riddler

At a recent Microsoft conference, the presenter did some quick programming that raised a gasp of excitement from the audience (I kid you not).  He inserted two question marks in a line of code as if they were an operator and Intellisense did not protest.

“Is that a new language feature in .NET 3.5?”, a member of the audience asked.

The presenter looked somewhat puzzled.  “No, it’s in 2.0.” 

At which point half the audience suddenly realized that this was a secret 2.0 feature they could now use to impress friends and colleagues, while the other half smiled knowingly because they had been using it for over a year.  Such is the way programmers distinguish the wheat from the chaff.

So, if you aren’t using the Null Coalesce Operator, yet, you should.  It is basically a syntactic device for setting a default value for nullable types.  The ?? Operator is the equivalent of the ISNULL function in T-SQL, or the NVL function in PL-SQL, and is very handy when you are trying to translate database values into your business classes.

If, for instance, you have a nullable number type in your Oracle database, or a nullable int in your SQL Server database, it is very convenient to map this to a nullable int in your C# business object.

int? myNum = null;

or

Nullable<Int32> myNum = null;

Being now able to represent this database value, you probably also want to be able to test for the null case and return an alternative value if it turns out to be true.  Here are four ways to do the same thing, in increasingly cool ways, because they are increasingly obscure.

With an IF ELSE block:

if (null == myNum)
    return -1;
else
    return myNum.GetValueOrDefault();

With a SWITCH block:

switch (myNum)
{
   case null:
        return -1;
   default:
        return myNum.GetValueOrDefault();
}

With a Ternary Operator:

return myNum == null ? -1 : myNum.GetValueOrDefault();

And with a Null Coalesce Operator:

return myNum ?? -1;

 

For those who think that in coding compactness == elegance, then this is the syntax for you.  For everyone else, it is a nice recipe you can use to impress co-workers at the next code review.  The most likely, and desirable, response will be:

??

Interop Forms Toolkit 2.0 Tutorial

I originally wrote the prize-winning Interop Forms article below for code project.  The prize, an XBox 360 Elite system, was pretty sweet.  Even sweeter, however, was the nod I received from the Microsoft VB Team here: http://blogs.msdn.com/vbteam/archive/2007/06/01/so-what-does-lt-comclass-gt-actually-do.aspx and here: http://blogs.msdn.com/vbteam/archive/2007/06/04/interopforms-2-0-tip-1-font-property.aspx.

The feedback from the VB Team, along with some help from Mike Dooney, led me along the right path to rework my C# templates a bit (the toolkit comes with only VB.NET templates).  The differences between the VB and C# templates highlight the fact that although the two languages are often believed to do the same thing once code is compiled to IL, this is not really the case, and in fact, when it comes to COM, VB does a much better job.

To be specific, the VB compiler creates additional code in IL to make a VB class’s events and properties visible in VB6, while the C# compiler does not. I had written the original templates with the assumption that the two compilers would write similar IL — because of this faulty assumption, the events thrown in a C# UserControl were never received in VB6. This has been corrected in the updated C# templates by including in C# the extra attributes and interfaces required to make the events visible — interfaces which the VB compiler automatically creates for you in IL.

The C# templates linked below also automatically create these interfaces for you. When you add a new event to your UserControl, you will just need to be sure to add it to the appropriate interface, as well.  The naming convention for the interfaces (one for exposed events, one for exposed properties) is simply the name of the UserControl class preceded by two underscores and one underscore, respectively. It’s a little bit more manual labor than the VB templates require — but not too much more.

From the feedback I received at code project, it is apparent that while the toolkit is a big help to developers still maintaining VB6 applications, the big gain is for FoxPro developers (really a very solid development framework) who can now squeeze a little more out of their interfaces when they need to, thanks to the Toolkit.

 

Diagram

Why use the Interop Toolkit?

A few years ago, the enterprise architects at the company I worked for came up with a central login mechanism for all the company’s applications using web services. They even provided code samples in Java, C# and VB.NET for using their new component. It was intended as a language agnostic solution. When we asked the architects what we should do with the VB6 applications that we were still supporting, the architects were nonplussed. They first provided some esoteric white papers on using SOAP with VB6, then they suggested that we upgrade all of our VB6 apps to .NET, and finally they conceded that VB6 apps simply didn’t have a place in their solution.

Had Interop Forms Toolkit 2.0 been available back then, we could have come up with an integration in under an hour. We would have simply copied the sample code into a new .NET User Control, used the Interop Toolkit to wrap it up as an ActiveX control, and then consumed the control in all of our VB6 apps.

Interop Toolkit 2.0 was just released at the beginning of May. The original Interop Toolkit already allowed VB developers to use .NET Forms in their applications. This is still in Toolkit 2.0, and appears not to have changed much.

What makes Toolkit 2.0 standout is its support for using .NET User Controls as ActiveX controls in VB6.

ActiveXControlHelpers

According to Microsoft, the toolkit is intended as part of a migration strategy for upgrading VB6 applications to .NET piece by piece. I am not sure this is how it is likely to be used, however, or even if it necessarily ought to be used in this way.

Toolkit 2.0 makes most sense as a tool that allows VB6 developers to take advantage of .NET features without being forced onto an upgrade path. Most VB6 applications that are still around obviously meet certain needs very well. Why fix something that isn’t broken?

There are times, however, when you may want to leverage .NET features in your VB6 application. For a long time your only two choices were to upgrade the whole application to .NET, or to forego the nifty new features.

Toolkit 2.0 provides a third option. Simply add the .NET feature you need as a control.

This tutorial will lead you through 1. a mock application that implements the sort of technology we would have used to solve the problem outlined above. It will also cover 2. installing the Interop Toolkit, 3. provide a reference app that gives developers the ability to use real multithreading in their VB6 apps, and finally 4. provide a how-to for integrating XAML files into VB6.

Interop for C# developers

Just as with the previous version, Interop Forms Toolkit 2.0 is geared towards VB.NET developers. The wizard, project templates and item templates that come with the Toolkit only come in VB flavors. This makes a certain amount of sense, since it will mostly be VB developers who will implement these .NET/VB6 integrations. Many developers like to work with both languages, however, and there may be integration scenarios where you need to expose pre-existing C# code to VB6.

For those cases, I’ve written the C# item template and C# project template linked above for Interop User Controls. Simply copy the project template zip file into your project templates folder (the default location is ...\My Documents\Visual Studio 2005\Templates\ProjectTemplates\Visual C#) and the item template zip file into your item templates folder (...\My Documents\Visual Studio 2005\Templates\ItemTemplates\Visual C#). I believe that these templates will only work with Visual Studio 2005, but I havn’t yet tested on older versions of Visual Studio to make sure.

For cases where you need to expose a C# Form, you can use the clever wizard and template written by Leon Langleyben, which I was able to get to work with a bit of tweaking — through no fault of Leon’s, since his add-in was written for the previous version of the Interop Toolkit (refer to the CSXamlEmbeddedForm project in the included CSharp Samples to see what the generated wrapper class should look like in C#).

Installing the Toolkit

Installing the toolkit is fairly straightforward. Navigate to the Toolkit Download Site and, of the three downloads available, run the InteropFormsInstaller.msi file. In most cases, this is all you need to do. When you open the Visual Studio.NET IDE, you should find the new templates, VB6 Interop UserControl and VB6 Interop Form Library, available when you create a new VB.NET project. Under your tools menu, you should also find a new wizard labeled “Generate InteropForm Wrapper Classes”.

If the new wizard does not appear in your tools menu, there may have been a problem installing it. Check Tools | Add-in Manager to make sure that this wizard is selected. If it is present and selected in the Add-in Manager, but still does not appear in your tools menu, you can run the following command in your command line to reset it: Devenv /resetaddin Microsoft.InteropFormTools.InteropFormProxyGenerator.Connect.

Installing the Toolkit on Vista

In order to use the Toolkit on Windows Vista, you will need to download both the msi file as well as the setup file to your harddrive. Then run setup. Running the msi file alone will generate an install error.

To use the C# UserControl templates on Vista, you will need to run Visual Studio as an Administrator. Right-click on the link to your Visual Studio IDE and select the Run as administrator popup menu option. This will let Vista’s UAC feature know that it is alright for the UserControl to write to the registry on build events.

Building a User Control

In this first example, the UserControl will take care of all the processing, and will just sit in the VB6 Form, while the example following it will demonstrate how to pass information between VB6 and VB.NET. Any code snippets will be in VB, though the source code samples linked above include both a VB.NET as well as a C# sample of the control.

In this example we use the Daily Dilbert web service to download a cartoon to our control (you will notice that the Daily Dilbert comes up a lot on CodeProject — for good reason; it happens to be one of the few interesting web services that can actually be used in public tutorials, since it does not require a fee or registration).

Open new project

Begin by creating a new VB6 Interop User Control project using the VB6 Interop UserControl project template. Name the project DailyDilbertControl. By default, a UserControl file is created called InteropUserControl.vb. Since this is the control name that will be displayed in your VB6 control panel, you should rename it to DilbertService.vb, to be more descriptive.

In your new project, you will find the following files: ActiveXControlHelpers.vb, InteropUserControl.bmp, InteropUserControl.manifest. ActiveXControlHelpers.vb, as the name suggests, includes several static helper methods that make the conversion of your UserControl into an ActiveX control possible. There are register and unregister methods, which add details about your control to the registry. There are methods that help convert things like color codes between the .NET scheme and the OLE scheme used in VB6. There is also a method that wires up your events to work with VB6. You can have multiple user controls in your project, but should only have one ActiveXControlHelpers file per project.

The InteropUserControl.bmp is used to display your control in the VB6 Toolbox. I will cover how to customize your ActiveX control image later in this tutorial.

Add a new web reference to the Daily Dilbert web service to your project. To do this, right click on your project and select Add Web Reference… A new dialog will pop up. Enter http://www.esynaps.com/WebServices/DailyDiblert.asmx for the URL and click on Go. Finally, rename the web reference to “DDService” and select Add Reference at the lower right of the dialog. Your Solution Explorer should now look like this.

AddWebReference 

Add a 650 by 215 pixel PictureBox called DilbertPictureBox to your UserControl, as well as a button called RetrieveButton. Create a new RetrieveButton_Click event handler by double clicking on RetrieveButton. Paste in the following code, which will call the web service and retrieve today’s Dilbert strip.

    Private Sub RetrieveButton_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles RetrieveButton.Click
        Dim myDilbert As New DDService.DailyDilbert()
        Dim DilbertMemoryStream As _
        New System.IO.MemoryStream(myDilbert.DailyDilbertImage())
        With Me.DilbertPictureBox
            .Image = Image.FromStream(DilbertMemoryStream)
            .BorderStyle = BorderStyle.Fixed3D
        End With
    End Sub

To finish making your control visible from VB6, just press F5 to preview the control, or simply build it. It will look like this in your Visual Studio UserControl Test Container:

DilbertControlPreview 

And that’s all it takes to build build an ActiveX control in Visual Studio.NET.

Adding an ActiveX Control Image

When you build a new control, InteropUserControl.bmp will be used as the default image for your component in the VB6 Toolbar. You can always use a different image, though. For this project, I want to use this image of Dilbert.

Dilbert

To add it, you first have to add the bitmap file you want to use to your project and set its build property to “content”. Now open the InteropUserControl.rc resource script file with notepad. DO NOT use Visual Studio to do this, as this will mess up your resource script file. InteropUserControl.rc can be found under the DailyDilbertControl project folder. Beneath the default 101 BITMAP InteropUserControl.bmp entry, add an additional entry specifying the custom bitmap you want to use.

changeresourcescript 

Save your resource script file. Now open ActiveXHelpers.vb and find the RegisterControl method. This is where registry entries are created. In the section where the bitmap file is specified, replace the default entry, “101”, with a reference to your own bitmap.

replacebitmap

Now rebuild your control to make sure a new compiled resource file is created. The new image should appear in the VB6 Toolbox rather than the default image.

vb6toolbar

More about adding ActiveX Control Images

You can use a different image for each UserControl in your project, but you will have to modify the ActiveXControlHelpers.vb file a bit to make this work. Alter the RegisterControl method signature to take a second string parameter, and then pass this parameter to the line where the code specifies the resource id of the image.

    Public Sub RegisterControl(ByVal t As Type, ByVal BitmapId As String)

    '...
    
    'ToolBoxBitmap32
    Using bitmapKey As RegistryKey = subkey.CreateSubKey("ToolBoxBitmap32")
    bitmapKey.SetValue("", Assembly.GetExecutingAssembly.Location & ", "  _
    & BitmapId, RegistryValueKind.String)
    End Using
    
    '...
    
    End Sub

Then, in each UserControl, add the BitmapId you want to use for your control to the RegisterControl call.

    <EditorBrowsable(EditorBrowsableState.Never)> _
    <ComRegisterFunction()> _
    Private Shared Sub Register(ByVal t As Type)
        ComRegistration.RegisterControl(t, "102")
    End Sub

Rebuild the entire project once more.

Adding the UserControl to a VB6 project

DailyDilbertComponent 

This is actually the easiest part. Create a new VB6 project. Press CTRL+T to add a new component to your form, and check the DailyDilbertControl library. Press OK. (Vista behaves a bit strangely when you try to add your ActiveX control. It will occassionally throw an error the first time you select OK, then will work normally the second time you do so. Just to be safe, click Apply first just to see if there is an error, and then OK.) Any UserControls in your project will now appear on the VB Toolbar. Simply select the control you want to use and draw it onto your VB6 form. Press F5 to see your .NET UserControl run in a Visual Basic 6 application.

vb6form1 

Adding True Multithreading to VB6

When I was working with VB6 on a regular basis, one of the main impetuses for upgrading to .NET was the ability to implement multithreading. Interop UserControls provide an easy way to add true multithreading to a VB6 application. In a common scenario, you may want the users of your VB app to be able to kick off a process and then continue with their work while the processing occurs in the background. To simulate this scenario, the reference code we are about to build will use a BackgroundWorker control that will perform a time-consuming process in the background while updating a progress bar. In the meantime, the users of the VB6 application that consumes the control can continue with their work.

Create a new VB6 Interop UserControl project called MultithreadedControl. Add a BackgroundWorker control named BackgroundWorker1, a label called LabelWarningMessage and ProgressBar called ProgressBar1. Paste in the following code.

    Public Delegate Sub StartEventHandler(ByVal simpleEventText As String)
    Public Delegate Sub FinishAsyncEventHandler(ByVal asyncEventText As String)

    Public Event StartEvent As StartEventHandler
    Public Event FinishAsyncEvent As FinishAsyncEventHandler

    Public Sub StartProcessing()
        Try
            RaiseEvent StartEvent(".NET process starting")
            Me.BackgroundWorker1.RunWorkerAsync()
        Catch
        End Try
    End Sub

    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, _
    ByVal e As System.ComponentModel.DoWorkEventArgs) _
    Handles BackgroundWorker1.DoWork
        'wait
        Static prog As Integer = 0
        While (prog < 100)
            System.Threading.Thread.Sleep(50)
            prog = prog + 2
            Me.BackgroundWorker1.ReportProgress(prog)
        End While
        prog = 0
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As System.Object, _
    ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
    Handles BackgroundWorker1.ProgressChanged
        Me.LabelWarningMessage.ForegroundColor = Color.Red
        Me.LabelWarningMessage.Text = "Working in background..."
        Me.LabelWarningMessage.Visible = True
        Me.ProgressBar1.Value = e.ProgressPercentage
    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, _
    ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
    Handles BackgroundWorker1.RunWorkerCompleted
        Me.LabelWarningMessage.Visible = False
        RaiseEvent FinishAsyncEvent("Interop User Control process finished.")
    End Sub
    
    Private Sub BackgroundWorker_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load
        Me.ProgressBar1.Value = 0
        Me.LabelWarningMessage.Visible = False
    End Sub

Finally, make sure that the BackgroundWorker events are hooked up to the handlers we’ve written.

backgroundworkerevents 

Also make certain that the BackgroundWorker’s WorkerReportsProgress property is set to true. Build the project.

Open a new VB6 project and add the MultithreadedControl component to your VB6 Form, as you did in the previous example. Also add a multiline TextBox control (Text1), a ListBox (List1), and a CommandButton labeled “Process” (Command1).

In order to receive events from the BackgroundWorker control, you will need to add an additional reference to the control. Click on the menu item Project | References… A reference to MultithreadedControlCtrl will already be checked off from previously adding it as a component. You will now need to also include a reference to the library MultithreadedControl in order to capture events thrown from the .NET Control.

MultithreadedControlReference 

Finally, paste in the following VB6 code. In this code, you declare a new reference to the control, this time decorated with the keyword “WithEvents” in order to expose the control’s events. Wiring up handlers for the events is based only on the names of the procedures, so you have to be careful when typing out the Sub routines that will be used in this way.

Before the underscore, always use the same name you used when you created the second reference (in this case “BackgroundEvents”). Then after the underscore, use the actual event name as it appears in your original .NET control. I’ve seen lots of problems posted to various message boards concerning problems with VB Interop event handling that basically came down to misspelling a handler’s signature — so be careful.

Dim WithEvents BackgroundEvents As MultithreadedControl.BackgroundWorker

Private Sub Command1_Click()
    Me.Text1.Text = ""
    Me.List1.Clear
    Me.List1.AddItem ("Start processing from VB6: " & DateTime.Now)
    Me.BackgroundWorker1.StartProcessing
End Sub

Private Sub Form_Load()
    Set BackgroundEvents = Me.BackgroundWorker1
End Sub

Private Sub BackgroundEvents_StartEvent(ByVal EventText As String)
    Me.List1.AddItem (EventText)
End Sub

Private Sub BackgroundEvents_FinishAsyncEvent(ByVal EventText As String)
    Me.List1.AddItem (EventText)
    Me.List1.AddItem ("Finish processing from VB6:" & DateTime.Now)
End Sub

This reference app basically demonstrates how a .NET BackgroundWorker can be used inside a VB6 application. Even while the processing is occurring, and updating the status bar to let us know how far it has gotten, the end-user can continue typing into the textbox. If you have never programmed in VB6, then this probably seems like a trivial accomplishment.

For those of us who have worked on Visual Basic 6 apps for large portions of our careers, it is a breakthrough.

VB6Multithreaded

Using XAML in VB6

You cannot build a XAML UserControl or a XAML Form and then consume it directly in VB6, unfortunately. You also cannot simply add a XAML Form to a Windows Application project and expose it that way. With a bit of finesse, what you can do is embed a XAML UserControl in a Windows Form and consume that in your VB6 apps. The following walkthrough will show you how.

Create a new VB6 InteropForm Library Project in Visual Studio, and call it XamlEmbeddedForm. Rename the default Windows Form to XamlForm. Now add a second project based on the .NET Framework 3.0 Custom Control Library (WPF) project template and call it XamlUserControl. You can add whatever XAML code you like, at this point. For the reference project, I’ve used the Cube Animation code found in the WPF SDK. Build the XamlUserControl project. In XamlEmbeddedForm, add a reference to the UserControl project. Also add the following four library references: PresentationCore, PresentationFramework, WindowsBase and WindowsFormsIntegration.

NewReferences 

You now will need to add some code to the FormLoad event in order to host the XAML UserControl in your .NET Form. The complete code behind should look like this:

Imports Microsoft.InteropFormTools
Imports System.Windows.Forms.Integration
Imports System.ComponentModel
Imports System.Windows.Forms

<InteropForm()> _
Public Class XamlForm

    Private Sub XamlForm_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles MyBase.Load
        ' Create the ElementHost control for hosting the
        ' WPF UserControl.
        Dim host As New ElementHost()
        host.Dock = DockStyle.Fill

        ' Create the WPF UserControl.
        Dim uc As New XamlUserControl.UserControl1()

        ' Assign the WPF UserControl to the ElementHost
        '  control's Child property.
        host.Child = uc

        ' Add the ElementHost control to the form's
        ' collection of child controls.
        Me.Controls.Add(host)
    End Sub
End Class

Rebuild your solution one more time for good measure. Then go to the Tools menu and select Generate InteropForm Wrapper Classes (if this menu option is missing, refer to the installation instructions above). This will add a new wrapper class to your project that can be exposed to VB6. Rebuild one last time to register your wrapper class in the registry. At this point, your .NET code is complete.

Open a new project in VB6. Open Project | References and check two items to add them to your VB6 project: Microsoft Interop Forms Toolkit Library as well as your .NET project, XAMLEmbeddedForm to add to COM wrapper for your .NET assembly to your VB6 project.

.NET Interop Forms have difficulty knowing when the host VB6 application starts and stops, so some extra code must be added to your VB6 application to handle this. Add the following code snippet to your VB6 Main Form so the .NET code is informed when these events occur.

Public g_InteropToolbox As InteropToolbox

Private Sub Form_Load()
    Set g_InteropToolbox = New InteropToolbox
    g_InteropToolbox.Initialize
    g_InteropToolbox.EventMessenger.RaiseApplicationStartedupEvent
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    g_InteropToolbox.EventMessenger.RaiseApplicationShutdownEvent
End Sub

We are nearly done. To open your .NET Form from VB6, just add a command button to your Main Form and handle its click event with the following code.

Private Sub Command1_Click()
Dim xaml As New XamlEmbeddedForm.XamlForm
    xaml.Show vbModal
End Sub

If everything goes right, when you click the button, you should see an animated cube, written all in XAML.

EmbeddedForm

Conclusion

This tutorial is intended to walk you through the steps needed to create a useful .NET/VB6 integration. It is also intended to give you a sense of the almost limitless possibilities that are open to VB6 developers now that this technology has been made widely available. Half a decade after people were foretelling the doom of VB6 as a development tool, we should come to terms with the idea that VB6 will still be with us for quite a while longer. Interop Toolkit 2.0 ensures that the many years left to VB6 development will be both graceful and productive.

sassy.net: Fall Fashions for .NET Programmers

janerussell

This fall programmers are going to be a little more sassy.  Whereas in the past, trendy branding has involved concepts such as paradigms, patterns and rails, principles such as object-oriented programming, data-driven programming, test-driven programming and model-driven architecture, or tags like web 2.0, web 3.0, e-, i-, xtreme and agile, the new fall line features “alternative” and the prefix of choice: alt-.  The point of this is that programmers who work with Microsoft technologies no longer have to do things the Microsoft way.  Instead, they can do things the “Alternative” way, rather than the “Mainstream” way.  In the concrete, this seems to involve using a lot of open source frameworks like NHibernate that have been ported over from Java … but why quibble when we are on the cusp of a new age.

Personally I think sassy.net is more descriptive, but the alt.net moniker has been cemented by the October 5th alt.net conference.  David Laribee is credited with coining the term earlier this year in this blog post, as well as explicating it in the following way:

What does it mean to be to be ALT.NET? In short it signifies:

  1. You’re the type of developer who uses what works while keeping an eye out for a better way.
  2. You reach outside the mainstream to adopt the best of any community: Open Source, Agile, Java, Ruby, etc.
  3. You’re not content with the status quo. Things can always be better expressed, more elegant and simple, more mutable, higher quality, etc.
  4. You know tools are great, but they only take you so far. It’s the principles and knowledge that really matter. The best tools are those that embed the knowledge and encourage the principles (e.g. Resharper.)

This is almost identical to my manifesto for sassy.net, except that I included a fifth item about carbon neutrality and a sixth one about loving puppies.  To Dave’s credit, his manifesto is a bit more succinct.

There are a several historical influences on this new fall line.  One is the suspicion that new Microsoft technologies have been driven by a desire to sell their programming frameworks rather than to create good tools.  An analogy can be drawn with the development of the QWERTY standard for the English-language keyboard.  Why are the keys laid out the way the are?  One likely possibility is that all the keys required to spell out “t-y-p-e-w-r-i-t-e-r” can be found on the top row, which is very convenient for your typical typewriter salesman.  Several of the RAD (Rapid Application Development — an older fall line that is treated with a level of contempt some people reserve for Capri pants) tools that have come out of Microsoft over the past few years have tended to have a similar quality.  They are good for sales presentations but are not particularly useful for real world development.  Examples that come to mind are the call-back event model for .NET Remoting (the official Microsoft code samples didn’t actually work) and the MSDataSetGenerator, which is great for quickly building a data layer for an existing database, and is almost impossible to tweak or customize for even mildly complex business scenarios.

A second influence is java-envy.  Whereas the java development tools have always emphasized complex architectures and a low-level knowledge of the language, Microsoft development tools have always emphasized fast results and abstracting the low-level details of their language so the developer can get on with his job.  This has meant that while Java projects can take up to two years, after which you are lucky if you have a working code base, Microsoft-based projects are typically up and running in under six months.  You would think that this would make the Microsoft solution the one people want to work with, but in fact, among developers, it has created Java-envy.  The Java developers are doing a lot of denken work, making them a sort of aristocracy in the coding world, whereas the Microsoft programmers are more or less laborers for whom Microsoft has done much of the thinking.

Within the Microsoft world, itself, this class distinction has created a sort of mass-migration from VB to C#; these are for the most part equivalent languages, yet VB still has the lingering scent of earth and toil about it.  There are in fact even developers who refuse to use C#, which they see as a still bit prole, and instead prefer to use managed C++.  Whatever, right?

In 2005, this class distinction became codified with the coining of the term Mort, used by Java developers to describe Microsoft developers, and C# developers to describe VB developers, and by VB.NET developers to describe their atavistic VB6 cousins.  You can think of the Morts as Eloi, happily pumping out applications for their businesses, while the much more clever Morlocks plan out coding architectures and frameworks for the next hundred years.  The alt.net movement grows out of the Morlocks, rather than the Morts, and can in turn be sub-divided between those who simply want to distinguish themselves from the mid-level developers, and those who want to work on betterment projects using coding standards and code reviews to bring the Morts up to their own level. (To be fair, most of the alt.net crowd are of the latter variety, rather than the former.)  The alt.net movement sees following Microsoft standards as a sort of serfdom, and would prefer to come up with their own best-practices, and in some cases tools, for building Microsoft-based software.

The third influence on the formation of the alt.net movement is the trend in off-shoring software development.  Off-shoring is based on the philosophy that one piece of software development work is equivalent to another, and implicitly that for a given software requirement, one developer is equivalent to another, given that they know the same technology.  The only difference worth considering, then, is how much money one must spend in order to realize that software requirement.

This has generated a certain amount of soul-searching among developers.  Previously, they had subscribed to the same philosophy, since their usefulness was based on the notion that a piece of software, and implicitly a developer, could do the same work that a roomful of filers (or any other white-collar employee) could do more quickly, more efficiently and hence more cheaply.

Off-shoring challenged this self-justification for software developer, and created in its place a new identity politics for developers.  A good developer, now, is not to be judged on what he knows at a given moment in time — that is he should not be judged on his current productivity — but rather on his potential productivity — his ability to generate better architectures, more elegant solutions, and other better things over the long that cannot be easily measured, run.  In other words, third-world developers will always be Morts.  If you want high-end software, you need first-world solutions architects and senior developers. 

To solidify this distinction, however, it is necessary to have some sort of certifying mechanism that will clearly distinguish elite developers from mere Mort wannabes.  At this point, the distinction is only self-selecting, and depends on true alt.net developers being able to talk the talk (as well as determining what the talk is going to be).  Who knows, however, what the future may hold.

Some mention should also be made concerning the new fall fashions.  Fifties skirts are back in, and the Grace Kelly look will be prevalent.  Whereas last year saw narrow bottom jeans displacing bell bottoms, for this fall anything goes.  This fall we can once again start mixing colors and patterns, rather than stick to a uniform color for an outfit.  This will make accessorizing much more interesting, though you may find yourself spending more time picking out clothes in the morning, since there are now so many more options.  Finally, V-necks are back.  Scoop-necks are out.

In men’s fashion, making this the fifteenth year in a row, golf shirts and khakis are in.