Archive for June, 2005

Symbol Recognition Interview Question

Yesterday, I came across this post on Jomo Fisher’s Blog about an interview question he’s considering. To quote the problem in case his blog dies before mine does. . .


Consider this code:const int WIDTH = 8;
const int HEIGHT = 8;
interface IGrid {
    int CountBlocksSet(int x1, int x2, int y1, int y2);
}
enum Shape {
    Square,
    Rectangle
}

static Shape Recognize(IGrid grid) {
    // Implement this.
}

The goal is to implement a symbol recognition algorithm. The symbol can only either be a square or a rectangle. The image always fits in an 8-by-8 grid (zero relative) represented by ‘grid’. The method CountBlocksSet will return the total number of blocks that are set within the area of the rectangle passed in.

Calling CountBlocksSet is very slow (imagine that it’s driving a physical scanner) so you want to call it as few times as possible. The speed does not depend on the size of the rectangle passed in to CountBlocksSet.



I misunderstood the question, so my results aren’t precisely relevant (hence the posting here and not in his comments). I thought that (0,0) (0,0) for example, would define the bottom left-most point on the grid, and therefore not define a valid area. It looks like he is actually considering that to define the bottom-leftmost square, where I considered the space between (0,0) and (1,1) to be the bottom-leftmost square.

So, my results may not correspond directly to his, but they might still be interesting. Play with this a bit and then compare your results to ours.  My best effort so far is 1.17 calls to CountBlocksSet per grid.

One pointer to verify algorithm correctness. We know that the number of squares should equal 204, the number of rectangles (including squares) should equal 1296, and the number of non-square rectangles would therefore be 1092.

Attached are testdrivercs.txt, the test driver and sample implementation, and gridcs.txt, the sample IGrid implementation.

mysolutioncs.txt is also attached, and includes my iterative improvements.

June 09 2005 | Geek Stuff | 1 Comment »

MSDN Nuggets from the UK

MSDN Nuggets

Don’t have the time to read a 10-page how-to article or watch a full length webcast? Try an MSDN Nugget, a webcast that takes you step-by-step to discovering new functionality or exploring a hot developer topic, all in 10-15 minutes. View them online or download for later reference.

http://www.microsoft.com/uk/msdn/events/nuggets.aspx

The few I’ve watched so far were “not lame.”

June 07 2005 | Geek Stuff | No Comments »

Fusion handles missing assemblies poorly

Junfeng Zhang’s .NET Framework notes (http://blogs.msdn.com/junfeng/archive/2005/06/03/424680.aspx) referenced a bug logged against Fusion and answered as “Won’t Fix”. I do not think that Microsoft has correctly understood or responded to the problem.

Here’s a quick summary of the bug:

  • Install two assemblies Binding.exe and ClassLibrary1.dll, with Binding dependent upon ClassLibrary1.
  • Delete ClassLibary1.dll.
  • Launch Binding.
  • MSI is not invoked for a repair, and the load fails with “Unhandled Exception: System.IO.FileNotFoundException: File or assembly name ClassLibrary1, or one of its dependencies, was not found.”

The problem is that Fusion allows the assembly binding to fail rather than invoke MsiProvideAssembly (…INSTALLMODE_DEFAULT…). The MSDN article describing how assemblies are located says that “If the assembly is not found after probing, the runtime requests the Windows Installer to provide the assembly.” This is referring to dependent assemblies, not to how Fusion attempts to locate assemblies directly invoked via Explorer.

Junfeng Zhang’s response is:

“We don’t invoke MSI install every time we see a binding failure. There are many by-design binding failure for resource probing. If we do that the perf will go to hell.

Instead, we query MSI before we invoke MSI install. If MSI says it has the component we then will invoke MSI install. In John’s case, the query returns nothing because ClassLibrary1.dll is in the wrong context/component.”

To address each point without hijacking that post. . .

There are certainly by-design binding failures, but these are most often for .resource assemblies, and do not result in a final Unhandled Exception attempting to load (right?). In this case, Fusion knows that the assembly is going to fail to load and that it is because there was an unhandled exception while attempting to load a dependency. The probing process already consumes significant time at this point, so investing additional time necessary to ask MSI to provide the assembly and repair if necessary seems like a good return on investment. The only time we’d take the hit of actually running a repair would be when MsiProvideAssembly detects that a repair is necessary.

Without knowledge of Fusion’s implementation, I can only speculate about how they are querying MSI in this scenario to see if it “has the component”. It doesn’t appear that Fusion ever loads MSI into it’s process, and no separate msiexec process is started. If Fusion used MsiProvideComponent (…INSTALLMODE_DEFAULT…) then the directly invoked assembly and any components in the component’s feature or feature parent would be reinstalled. Even if Fusion is somehow querying MSI in this scenario, doing so for only the directly invoked component would be almost useless in a real-world scenario. Very rarely would we have an assembly with no dependencies.

I’m not sure what “the query returns nothing because ClassLibrary1.dll is in the wrong component” means. MSI only allows one assembly per component, so I assume that “wrong component” just means “not the component we’re specifically verifying”. Even that is suspect, however, since a Component’s state can only be accurately evaluated in the context of a Feature. The “wrong” thing here seems to be Fusion’s implementation of the described functionality. Fusion should be using the MsiProvideComponent method rather than directly referencing a component out of the context of the associated feature.

The best solution would seem to be that if an assembly fails to bind dependencies after probing, the runtime requests that Windows Installer provide the assembly; the same solution that the documentation indicates has been implemented.

June 06 2005 | Geek Stuff | No Comments »

Curiosity killed the task

I was reminded today why two of the traits of a great tester are curiosity and a willingness to share information

We run test cases we run after every build to confirm that the build is good enough for deeper testing. This “Build Verification Test” failed in the lab, and I had already verified that the issue didn’t occur in my local VMWare Workstation image, so it seemed likely that there was something different in how I was testing and the BVT. I went upstairs to the lab to dig into why a particular service couldn’t be removed.

I sat down and got my bearings and was looking over the logs and current state of the machine when Robert, a tester I’d worked with when we were defining and implementing DCOM security settings compatible with Microsoft Windows Server 2003 SP1. He doesn’t usually see me in the lab, and asked what was going on. After a very brief conversation, Robert mentioned that the problem might be related to another issue he’d reported in the same build in which a process sometimes hangs. The two seemed likely to be related since the most common reason that a service won’t uninstall is that it cannot be stopped, and his process and my service are related.

Sure ’nuff, after some quick tests, I was able to confirm that my issue was a side-effect of his issue.

An insecure tester would have declined to offer any information in order to avoid being incorrect or rebuffed.

A merely competent tester would have ignored me and efficiently gone about his or her duties, effectively quelling any curiosity.

Robert saved me several hours of research because he was curious and because he was willing to share information. He not only earned his pay today, he also helped me earn mine, and that’s what teamwork is all about.

June 03 2005 | Geek Stuff | No Comments »

NMAKE - Reversing the error code from findstr or grep

If you’re using nmake, you’ll be familiar with this problem… I have logged some process, now I want to check for an error string in the log and terminate my build if it appears, and I don’t want to have to create a .CMD file to do it. The problem is that tools like grep and findstr return a success code when they find something, and that’s the opposite of what we want.

Here’s a quick way to reverse the error code: @findstr “$(TheErrorString)” “$(TheFile)” && exit /b 1 || exit /b 0

This works because. . . && means - Run this command if the previous command completed successfully

|| means - Run this command if the previous command did not complete successfully

June 03 2005 | Geek Stuff | No Comments »

Don’t fix that, I’m using it!

Today, a coworker and I were in the restroom washing up after lunch. We were irritated to find that the roll of paper towels was not in the usual place on the shelf. To our chagrin, we discovered that the roll was missing from its familiar place on the shelf because the dispenser was fixed.

People quickly adapt to the situation as it exists. In many cases, we come to prefer the existing, “wrong” state of affairs to the “right” state if the “right” state requires a change in our habits. In religion, we prefer darkness to light (John 3:19-22). Psychology and cultural anthropology students learn about Stockholm Syndrome, and the power of habit. In politics, we continue to elect the same leaders despite our incessant complaints about those same leaders.

The tyranny of the familiar also plays a role in software development and in the paradigm conflict between Open Source Software (OSS) and Commercial Off-The-Shelf Software (COTS).

As Rich Kulawiec said, “Any sufficiently advanced bug is indistinguishable from a feature.” It is not uncommon for the alpha-geek to fix a long-standing bug only to have customers frustrated and annoyed because their business processes had to change or their mission-critical custom feature no longer works.

OSS projects introduce another dynamic. In addition to the up-front impact of implementing a new software package, the very nature of OSS tends to make the software more volatile. As geeks tweak OSS solutions, we break the products’ perceived affordances.The new and improved version may indeed be better, but it is also different. The hallmarks of a successful OSS project, ongoing development and wide-spread adoption, compete against one another. The same buzz of activity that makes the project attractive to geeks can make it unpalatable to the average user.

Product teams without a good understanding of the end-user, a clear vision, and good leadership will be particularly prone to forgetting (or deliberately ignoring) that old and familiar trumps new and different for many users. A good product manager or customer advocate helps to balance “better” against “familiar”, but, ultimately, geeks must become more active participants in this process.

One of the hallmarks of a geek is a love of things that are new and different, but we also display a counterintuitive love of things old and arcane. We find pleasure in the familiar tools, toys, and technologies of yesteryear. We like command-line interfaces, classic arcade game emulators, and stories half a century old. Perhaps we are more like “them” than we would like to think; perhaps there is hope that we may yet learn to relate to our users.

June 01 2005 | Geek Stuff | No Comments »