The transition to Microsoft's brave new world of managed code will probably take a decade, during which time Windows programmers will struggle with the complexities of a hybrid managed/unmanaged environment -- both in the Windows OS itself and in the componentized applications and services layered on top of it. Instrumenting these very different programming environments -- so that developers can analyze, profile, and more effectively debug programs straddling the unmanaged and managed worlds -- is a big challenge that Compuware Corp.'s latest offering, DevPartner Studio 7.1, tackles fearlessly.
The DevPartner suite, which integrates deeply and gracefully with Visual Studio .Net 2002 or 2003 (I tested with both versions of the integrated development environment), supports the following activities in addition to run-time error detection: source-code review, code coverage analysis, memory analysis, profiling, and analysis of distributed applications. To perform one of these activities, select it on the VS .Net toolbar, optionally adjust the instrumentation that DevPartner will insert (in the case of unmanaged code), then debug (or in some cases just run) the application, and analyze results in the VS .Net document pane. Resulting data files accumulate, by activity type, in DevPartner's Solution Explorer.
To exercise the suite, I worked with open source indexing and search engine NLucene, which is a C# port of the popular Java-based engine, Lucene. I used DevPartner Studio to analyze the NLucene library, to analyze a program that indexes a batch of HTML files, and finally to analyze an ASP .Net application that searches that index.
Reviewing the Source
The source-code review feature, available for C#, VB .Net, and VB6, scanned the C# files and produced a report that was sometimes pedantic, and sometimes cogent and educational. Warnings about recursion, hard-coded strings, or member-variable names fall into the pedantic category. I assume developers are grown-ups who understand the consequences of these choices. Much more interesting are warnings that teach developers about platform subtleties. The warning ("Type not excluded from use by untrusted code") falls into this latter category. When an assembly is unsigned, as my build of NLucene was, you can still enforce trusted access by adding appropriate attributes to the source code. DevPartner identified the problem and illustrated the fix -- a nice example of how an intelligent automated assistant can work with a developer to improve code quality.
Some of the rules that drive code review are hard-coded into DevPartner, but others are available for inspection and modification in a rules editor. A shop that wants to enforce its own naming conventions, or classify new coding idioms, can do so. Compuware could, and arguably should, host a service for developers who would like to collaboratively define and share such patterns. The .Net CodeDOM, which, as the name implies, is a document object model for parsed code, suggests another intriguing possibility. Currently DevPartner's rules editor relies on regular expressions to define the patterns that trigger warnings. In theory, CodeDOM will enable higher-order pattern recognition that's also independent of the source language. I'll be interested to see if a future DevPartner release exploits that opportunity.
Analysis From All Sides
Using the DevPartner profiler to explore the behavior of NLucene during the indexing phase, I uncovered no surprises but made some interesting observations. The split between time spent in application vs. system code, for example, was 75:25. Most of the 25 percent spent in system code was in the .Net run time (22 percent), only a little in the Windows kernel (3 percent). At a method level within NLucene, low-level I/O was the dominating factor. I learned that my use of an option to optimize the generated index (by merging segments) cost very little extra time.
A snapshot of memory use while running the indexer showed me how the optimizer's consumption of memory was spread among short-, medium-, and long-lived objects. I was also able to invoke the garbage collector and observe its effects. Why bother? It's true that .Net's generational garbage collector will eventually clean up your act in most cases, but in the managed environment you still need to use memory responsibly. The ability to find out which objects hang around longer than they should is of tremendous value to the .Net programmer -- or, for that matter, to the Java programmer, to whom Compuware's DevPartner Java Edition offers similar capabilities.
Once the index was built, I created an ASP .Net-based Web form to search it. Then I fired up the distributed analyzer, which injected itself into the browser's process and also the Web server's ASP .Net process. From these vantage points, it collected an astonishing wealth of event detail as I ran the application. DevPartner showed the interplay between native and .Net code, the flow of events as the browser makes the request and the server handles it, and much more. Here, as everywhere in DevPartner studio, vast quantities of data are reduced to a clean and effective set of linked information displays that are easy to understand, navigate, and customize.
Although DevPartner Studio's newest features are .Net-related, you can also still use all of its pre-existing features for analyzing COM and ActiveX code written in C or C++ and for validating Win32 API calls. The ability to explore both the .Net and "legacy" realms deeply -- and simultaneously -- is a powerful asset that's likely to remain valuable for a long time to come.