Iñigo Montoya: "Naturally, you must suspect me to attack with Capa Ferro" Man in Black: "Naturally… but I find that Thibault cancels out Capa Ferro. Don’t you?" Iñigo Montoya: "Unless the enemy has e'studied his Agrippa… which I have."
- how to spot REAL talent (in a fight to the death), from "The Princess Bride"
How can you identify the "Evil Mort"s, and the wrong kind of "Einstein"s, during an interview, in order to avoid hiring them? Below, are the actual guidelines I recommended at my previous company (updated with .Net 3.0/3.5 references), which we used to evaluate new hire candidates for open .Net engineering positions. I purposely used very open-ended questions intended to maximize the candidate's opportunity to sell themselves and demonstrate some evidence of passion, a willingness and ability to learn, and sensitivity to maintenance and process concerns... IN ADDITION to testing their understanding of .Net. We needed candidates who were still able to support unmanaged C++ and MFC code, so each candidate first underwent a separate, fairly rigorous, C++ exam, and my portion of the interview didn't involve any actual coding.
New Hire Candidate .Net Interview Questions
We should be seeking PROFESSIONAL Windows developers – candidates who not only have a good understanding of .Net (as well as MFC and C++), but who are PASSIONATE about software, and who can also think in terms of ARCHITECTURE and development PROCESS.
Many of the questions below do not have “correct” answers. We’re looking for responses that demonstrate thinking beyond simply implementing assigned tasks (ie: “I think unit testing is a waste of time because…”, or “I prefer Lowy’s component focus to the inheritance focus in Microsoft’s class design guidelines because…” etc.)
General (10 mins):
1) General questions, based on examination of the person's resume
What made them decide to leave companyA after 8 years? Why did they only stay at companyB for 6 months? How many developers were on projectY? etc.
2) Try to separate development technologies in which they have MEANINGFUL experience (and interest), from the usual dump of token resume keyword references.
Do they consider themselves to be primarily a C++/MFC developer with some .Net experience, or vis-versa? Do they have more of a back-end, or GUI, focus? Has their .Net experience primarily been with ASP.Net, or desktop clients? Did their C++ experience extend into COM/ATL, or C++/CLI? Any managed or unmanaged DirectX? What experience do they have with specific remote communications and data access technologies? etc.
3) What .Net authors/resources do they recommend, or consider to be required reading for developers, and why? Do they track any RSS feeds? If they can’t come up with any .Net examples, what about resources for other development technologies? What was the last development-related book that they read? How much experience with .Net 3.0/3.5? Have they worked with LINQ, Lambdas, Blend...? Have they heard of F#? (ie: do they stay CURRENT with engineering practices and technologies?)
Qualified developers should know some of the Windows dev. community luminaries, and have definite opinions on good (and bad) books and online resources (favorite Blogs etc.). I would probably expect them to name MSDN Magazine (certainly MSDN online), and at least one of Richter, Sells, Lowy, Petzold, Adam Nathan on WPF etc. Non-.Net references might include Scott Meyers, Martin Fowler, Kent Beck, Bob Martin, Richter’s Advanced Windows, Don Box on COM, Prosise on MFC, MFC Internals… More than any other question, I think this identifies desirable candidates. Developers who are not actively keeping up with the evolving technologies are dead weight.
Attitude Check (20 minutes):
1) What was the “best” project they were ever on? Why (what made it so good)?
We should see some evidence of PASSION in response to this, and the next question.
2) What was the WORST project they were ever on? What made it bad, and what should have been done to FIX it?
Developers who are passionate about software are constantly analyzing the development process, and will have strong opinions about how things OUGHT to be done – while still being reasonable about the need to accommodate trade offs for valid business concerns.
3) What would they consider to be important coding guidelines?
They should express moderately pro-guideline feelings, and be able to list at least a few specific examples, such as not exposing member fields, not using magic numbers, avoiding multiple classes in a single file, some reasonable approximation for when method size could indicate a problem… Ask how they would ENFORCE a coding standard.
4) Determine the extent of the candidate’s understanding of (and attitude toward) modern STRUCTURED development cycle and process elements.
Ask them to describe the process they would set up to ensure successful delivery of a product, on a project staffed by a small team of junior developers, where they had been given complete authority over all aspects of the development process, able to define exactly what needs to occur, and in what order. The candidate’s answer should reflect some reasonable middle ground between fascism and anarchy, and might include mention of requirements, design and specifications, code reviews, handling of change requests, unit testing, coordination with QA, milestones, the use of specific tools such as CruiseControl… and possible mention of MSF, Scrum, or other formal methodologies. Do they like or dislike particular methodologies? What conditions might cause them to increase or decrease the level of "agility" in their process?
Base Line Technical (30 mins):
(Ask them to briefly identify, and expand on the significance of, terms they recognize in the list below)
A qualified candidate should be expected to be able to use many of these topics as a launching point, to describe related technical and process issues, whether it be the role of Design Patterns, or technical differences between .Net and MFC, or the trend toward process support in the IDE, implementation of the Dispose pattern etc.
- CLR
- Internal
- Delegates
- DRY
- Singleton (probe general knowledge/use of Design Patterns)
- UserControl vs. custom control
- Dataset
- Marshalling into UI thread
- Attributes
- NGen (probe knowledge of JIT compilation)
- Patterns and Practices Group (PAG)
- Refactoring
- lock(this) -- do they understand the problems with this pattern?
- Test-Driven Development (TDD), or Behavior-Driven Design
- S.O.L.I.D
- Visual Studio Team System (VSTS)
- Enterprise Library
- Juval Lowy, Chris Sells, Jeffrey Richter… others?
- Reflection
- Xaml
- Extension Methods
- FxCop
- Lambda
- Dispose
- WCF/WPF/WF
- P/Invoke
- Continuous Integration
- Func<T,TResult>
- “Agile” Development
- CodeDOM
- DataTemplate
- ControlTemplate
- LINQ
- Blend
- Attached Property
- MVC/MVP/M-V-VM
- Routed Events
- EndPoint
- F#
- SOA
In terms of evaluating a candidate's performance in this "vocabulary" section of the interview, when the candidate sees "Singleton" in this list of terms, its expected that they will be able to identify it as a Design Pattern, and we can use this as a lead-in, to discuss the use of patterns in general. If they display familiarity with the debate over the advisability of USING singletons, it shows that they are plugged into the developer community, and possibly gives some indication of the degree of passion they have on design issues (watch for overly-contentious foaming-at-the-mouth radicals). If the candidate can discusss double-check locking in the context of a singleton, it provides some additional clues on the depth of their engineering expertise, and if they are aware that CLR rules for static constructors can eliminate the need for double-check locking, it suggests the candidate may be less likely to write unecessary code in ignorance of existing framework features.
A physicist we hired, partly because of her impressive "language lawyer" level of C++ expertise, left for a two-week trip back to her home country, after several months of knocking out project features at what had seemed to be a very respectable pace. In her absence, the project technical lead tried to implement what should have been a minor change, and ended up spending several days tearing his hair out, just trying to make some sense of her code. When the original developer returned, she explained that MFC simply wasn't "object-oriented enough", and that she had essentially just replaced large areas of the framework with her own, more "correct", versions of existing APIs. According to the usual definition of "Mort"s and "Einstein"s, this engineer was definitely an Einstein, but she was an Einstein who was FOCUSED ON THE WRONG THINGS! Aside from the fact that our code base was now inconsistent with all published API information and no one else could ever hope to understand or work on her code, her decision also guaranteed that we would be treated to all kinds of random errors whenever Microsoft got around to updating its MFC dlls.
As frustrating as it can be to deal with "Mort"s, the tendency of many "Einsteins" to resist learning (or unnecessarily insist on replacing) standard framework capabilities, can derail projects, and permanently cripple code bases, so it always bothers me when I hear respected figures in the developer community suggest that testing for knowledge of specific APIs is irrelevant when it comes to evaluating engineering candidates.
"Our philosophy is that we're hiring for the long term, and any technology you happen to know right now may well be obsolete next year"
- from Joel Spolsky's (in all other respects, definitive) guide to hiring developers, "Smart And Gets Things Done"
I agree, in principle, when Joel says it makes absolutely no difference whether an engineering candidate is familiar with a particular technology or buzzword -- until you discover that those same developers who are unfamiliar with "MSMQ" turn out to have been supporting a .Net-based client-server application for the past several years, and written a complete network fault recovery system from scratch... or their own transaction support... or their own approximation of role-based security... Again, these are examples of Einsteins hard at work, when what you really needed was an API expert (at least until they could demonstrate actual DEFICIENIES that couldn't be addressed just by modifying or extending the existing feature set). Similarly, the Einstein who claims that an understanding of Design Patterns and Object-Oriented (Behaviour-Driven) design, and unit testing... trumps any need for expertise with a specific development framework... may now be sidetracking the members of your project into building and supporting a "better" MVP-based UI framework, when the cost-benefit trade off on that, especially for non-trivial, highly-customized, WPF-based UIs, is still far from clear.
For the kind of projects I work on, (and that most companies who are interviewing Windows developers usually seem to be seeking to staff), the ability to write low level data structures or sorting algorithms, which is how many organizations test for what they think are Einsteins... is completely irrelevant (and absolutely the LAST thing you ever want your developers to even THINK about doing), while an in-depth understanding of the various considerations involved in using, combining, and modifying, elements chosen from the huge pool of components available in the BCL and elsewhere... is absolutely ESSENTIAL. Testing a candidate's understanding of specific APIs also gives you some indication of whether that developer has the potential to be productive IMMEDIATELY. you want your new engineering hires to be familiarizing themselves with the PROBLEM DOMAIN rather than spending their time to learn a new development API. You also want to ensure that a new developer's code is not going to cause problems for everyone else on the project and, no matter how brilliant someone may be when it comes to CS fundamentals or high-level concepts, with the learning curve for new technologies like WPF, and the breadth and depth of the ever-evolving framework, its probably not unreasonable to expect code written in the first six months against an unfamiliar API to require an extensive amount of rework.
I've occassionally recommended candidates who impressed me as being super-smart, even though they had no direct experience with the specific Windows development technology we were expecting them to use, but only when their performance in the interview suggested they had made the effort to aquire an IN-DEPTH understanding of whatever technology they HAD been using -- with special bonus points for the rare candidate who could demonstrate familiarity with preliminary CTP releases of UPCOMING Windows dev. technologies, since they were unlikely to waste time inventing their own solutions without bothering to at least first fully understand the capabilities of solutions already provided, or which might soon be available.
In fifteen years as a developer, I've had to rewrite ALOT of code created by Einsteins with advanced degrees (my only degree is in Asian Studies), and show them how to write maintainable code and make proper use of available framework features... while I freely admit that I couldn't write a basic sorting algorithm or low-level data structure to save my life.
The only time I ever missed not having a more formal Math/Engineering background, was when I once got stuck trying to calculate a particular coordinate in the drawing routine for my ActiveX "CoolLabel" control, and I ended up finding the solution (calculation of a "polar" coordinate) only by flipping through an illustrated Math encyclopedia three days later.
(Hey, this feature wowed them back in '97, and the associated mapping product sold hundreds of thousands of copies)
Managers at the company I worked for in Japan were surprised that I knew the term "Mado Giwa Zoku" ( ), or "window-seat tribe", which dated from the earlier economic era of the lifetime employment system, where employees who had proven themselves to be hopelessly useless were still kept on the payroll, and just given a desk by a window somewhere, out of everyones else's way. Unfortunately, in software, there's just no way to keep someone out of everyone's way while still allowing them to touch the code base. I was reminded about that recently, as I read about the tendency to trash "Mort", in at the first Alt.NET conference, recently held in Austin, Texas.
"Mort", "Elvis", and "Einstein" were personas defined in the developer tools group at Microsoft many years ago, to describe the three categories of developers that made up the target market. "Mort" is the pragmatic developer who only studies engineering issues in the context of completing some assigned task, and learns JUST ENOUGH to let him complete that task. "Elvis" consults a variety of development resources to help him improve the quality of his engineering, and expects tools to enable him to create custom controls and other alternatives to the canned solutions that Mort relies on. "Einstein" is continuously seeking to expand his understanding of engineering issues, far in advance of receiving any specific feature request on which to apply that knowledge, and he demands tools that enable him to craft more sophisticated lower-level solutions.
Alt.NET is a reaction to what some Agile practitioners consider to be Microsoft's preoccupation with simple drag-and-drop development, at the expense of providing truly MEANINGFUL support for modern Agile practices. Alt.NET supporters complain that Microsoft introduces its own, sometimes half-baked, alternatives to established, more fully-featured, open source tools, creating difficulties for developers trying to transition to Agile. Although Microsoft's original definition did not imply any criticism of "Mort" developers (it stood for "mortal"), many participants at the recent Alt.NET conference seemed to take the position that the developer community needs to quit coddling Morts, and focus on how to integrate best-of-breed (presumably, non-Microsoft) tools and practices to support "true" .Net-based Agile development. Other conference participants described Mort as an "Elvis in training", while some Microsoft attendees took issue with the overt Microsoft bashing.
There are certainly Good Morts, who may be junior developers overwhelmed with all the issues involved with real-world engineering projects, or developers who have only ever worked on trivial projects, or even non-developers occasionally "re-tasked" to write code -- such as the hardware engineer who picks up a copy of "Master .Net in 4 Minutes" and delivers a (surprisingly functional) FrankenApp in two weeks. Good Morts can be mentored, or inspired, or simply replaced with more qualified resources when an application reaches a level of complexity or importance to justify funding the change. But, for every Good Mort, there always seems to be a bench of Evil Morts, who are either unable or unwilling to make the effort required to bring their work up to an acceptable level. Evil Morts suck time and energy from their peers, who constantly have to decypher and fix Mort's code, and who have long since given up trying to explain basic software engineering concepts like "separation of concerns", or "refactoring", or "WouldYouPleaseFollowSomeFreakinCodingGuidelines'".
The tough question is what to DO with Morts. Its a little naive to imagine you can avoid or eliminate them completely. The cost and scarcity of really good developers (whose fully-loaded cost here in Silicon Valley can top $150K), may have caused your company to settle for whoever it could get. Maybe you got stuck with the bosses best friend's nephew (a story for another time). And then there are all those other pesky real-world concerns liable to be raised by managers...
"We can't just get rid of Mort! He's been with the company for fifteen years. He's a nice guy, with a wife and kids and a mortgage... who spends his weekends delivering meals to shut-ins..."
or...
"What? Reduce headcount in my section (and my perceived importance to the company)?!!!
or (I'm not making this up)...
"Yes, we know Mort's a problem. But he's been here N years, and we have to be careful to avoid being sued for age discrimination"
Meanwhile, Mort still makes his all member fields public, passes eight separate parameters to hundred-line C# methods, unwittingly writes thousands of lines of code to duplicate capabilities baked into the BCL, sees nothing wrong with cutting and pasting the same ten-case switch statement into three different locations in the source, and will soon be writing reams of unmaintainable unit test code to accompany his convoluted implementation code.
Find some way to keep Mort out of your code base, because the situation is only going to get worse, as the learning curve associated with each new development technology continues to grow steeper, as new practices like Scrum shorten and intensify the development cycle, and make it ever-more-critical for developers to be able to rely on the quality of each other's code, as open source alternatives continue to inflate the size of the "standard" developer tool set, and as the PACE OF CHANGE to tools and practices accellerates to become almost continuous...
Maybe Mort has interests or talents that could be put to use somewhere else in the company. Maybe you can offer him some financial incentive to leave (His fellow developers would probably offer to chip in -- and, if he goes to work for your competitor, you benefit TWICE!). As a last resort, the closest developer equivalent to Mado-Giwa-Zoku would be to assign Mort a solo project... that you never plan to ship.
The path toward becomming an "expert" Windows developer used to be pretty straightforward. You needed only the most basic understanding of C++ to qualify for a job (if you could define a virtual function and explain the "slicing" problem, you were in), you worked your way through Kruglinski's introductory text on MFC, skimmed each month's issue of "Microsoft System's Journal", and eventually learned to check the index of Prosise's "Programming Windows With MFC" and the Table of Contents of the "MFC Answer Book" before starting any feature, since there was a good chance the authors had already done most of your work for you. After two or three years of implementing features, you'd probably gotten around to tackling "MFC Internals", and Richter's "Advanced Windows", and maybe Cooper's "About Face", and one or more of McConnell's treatises on process ("Rapid Development", "Code Complete"...), which would put your skills pretty much on par with those of senior Windows developers working just about anywhere. If you were REALLY concientious, you might have picked up a copy of Petzold's "Programming Windows", the GOF's "Design Patterns", and maybe even a few business-side books like Cusumano's "Microsoft Secrets" -- and then tried to figure out how any of this related to pounding out new features in whatever convoluted MFC mess you happened to be maintaining. For tools, you relied exclusively on Visual Source Safe and the Visual Studio IDE, and probably watched with detached interest every year or so, as managers fended off some wild-eyed radical agitating to switch to Borland's OWL.
The last time I set aside some serious "study time" between jobs (on that occassion, it was involuntary -- the company shut down and laid everyone off), I had already done all of the above, and I ended up spending ten months hanging out in coffee shops, reading Eckel, Meyers, and others on C++, and programming simple demos in DirectX, before taking what turned out to be a really great opportunity, writing a DX-based digital video editing utility at a hardware startup. At the time, I had actually been toying with the idea of getting into game development (what developer hasn't?), but suicidal margins were taking out those companies left and right, with a thousand eager job candidates for any position at one of the remaining "name" companies.
Since then, of course, the bar for attaining (and maintaining) any degree of Windows developer "expertise" has been raised, requiring continuous monitoring of dev. community RSS feeds, evaluation of CTP builds of upcoming technologies, and a reference library of critically important material from Lowy and Sells and Richter... and that was BEFORE this wave of .Net 3.0/3.5 tools and technologies that's now looming overhead.
In my current "sabbatical", I'm exploring different ways to architect and implement non-trivial WPF/WCF/WF/Linq applications, while trying to maintain the discipline required to write associated unit tests, and work within the confines of a continuous integration build environment. I'm trying to understand issues like whether it is still useful, in WPF, to apply the WinForms technique of centralizing marshalling of communications to the UI thread in the business layer (via AsyncOperation), BEFORE raising events to the UI. Are there situations where data binding to UI elements is NOT a practical strategy? When is it better to set bindings manually, versus relying strictly on Xaml (via ObjectDataProvider etc.)? How should source code be organized to best support CI automation? How do implementation strategies, such as the use of the Singleton pattern, impact unit testing, Xaml integration, and the ability to "hand off" the entire UI layer to designers working with Blend? Is there a real net benefit to adding extra architecture layers just to support unit testing of the UI? If so, is it better to use some canned framework like SCSF/Acropolis, or just to roll your own, as Jeremy Miller has suggested? I've also spent a surprising amount of time and energy resolving issues with open source tools, many of which suffer from REALLY poor documentation, and sometimes don't want to play well together.
I figure its going to take me another month or two before I'm satisfied that I'm able to provide definitive direction to a development department, rather than having to suffer someone's else's WAG (Wild *ss Guess) approach to implementation or dev. process. My timing may have been a little early, in terms of widespread .Net 3.0/3.5 adoption and available job opportunities, but as long as I haven't jumped the gun by two or three YEARS, I think I can probably endure this pain and suffering a while longer.
Now, if you'll excuse me, my latte's getting cold, and I want to finish testing this new validation strategy in time to catch a matinee at the theatre next door...
|