<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Metrics</title>
        <link>http://geekswithblogs.net/terje/category/9067.aspx</link>
        <description>Metrics</description>
        <language>en-US</language>
        <copyright>terje</copyright>
        <managingEditor>terje@osiris.no</managingEditor>
        <generator>Subtext Version 0.0.0.0</generator>
        <item>
            <title>Code Metrics - suggestions for appropriate limits</title>
            <link>http://geekswithblogs.net/terje/archive/2008/11/25/code-metrics---suggestions-for-appropriate-limits.aspx</link>
            <description>&lt;p&gt;I like Code Metrics.  They give a certain "objective" evaluation of a piece of code.  You can use it for yourself just to make it pinpoint potential trouble areas, or just some code where you were a bit sloppy - happens from time to time......  And when you're going to do a peer review, it's much better to point to some numbers instead of  the "This code sucks....."-thing.   So when it finally arrived inside Visual Studio I was delighted.  &lt;/p&gt;
&lt;p&gt;There are however a few things there which should be nice candidates for the next upgrade.&lt;/p&gt;
&lt;p&gt;First, it doesn't work on Team Builds, and it won't be fixed in TFS 2008.  The people I spoke to at the PDC said it would be integrated with team build in TFS 2010 !  &lt;/p&gt;
&lt;p&gt;Second, the levels they have for red/yellow/green limits are strange.  It is only the Maintenance Index that "powers" these flags.  At the method level they are fixed at &amp;lt;10 for Red and &amp;lt;20 for Yellow.  The Maintenance index (MI) is a normalized variation of work done at Carnegie Mellon University, see &lt;a title="http://blogs.msdn.com/fxcop/archive/2007/11/20/maintainability-index-range-and-meaning.aspx" href="http://blogs.msdn.com/fxcop/archive/2007/11/20/maintainability-index-range-and-meaning.aspx"&gt;http://blogs.msdn.com/fxcop/archive/2007/11/20/maintainability-index-range-and-meaning.aspx&lt;/a&gt; for information on it, and how they normalized the MI. The original metric had a maximum at 171.  In VS2008 MI is defined to have a range from 0 to 100, so in principle it is scaled down by a factor of 100/171. In addition they did not allow negative values, which is just fine. &lt;/p&gt;
&lt;p&gt;However, a &lt;a target="_blank" href="http://doi.ieeecomputersociety.org/10.1109/2.303623"&gt;study&lt;/a&gt; made by Hewlett Packard (using the original metrics), published in IEEE Computer back in 1994,  where they analyzed several projects found that levels below 65 should be in the red, yellow from 65 to 85, and green beyond that.  Normalizing these limits again, suggest values of 39 and 50 respectively, which is far higher than the 10/20 limits now in effect.  My own experience have been to set these levels at 40 and 60, quite close to the HP findings.  Code written with MI metrics values below 40 is rather nasty, so I believe these values still holds, even if the study is a few years back. &lt;/p&gt;
&lt;p&gt;For the Cyclomatic complexity metric, which is a often used metric, the recommendations for red/yellow/green is Green &amp;lt;10, Yellow 10-15/20 and Red &amp;gt; 15/20.  See this &lt;a target="_blank" href="http://www.aivosto.com/project/help/pm-complexity.html"&gt;article&lt;/a&gt;.  Some also says everything above 10 should be  red. &lt;/p&gt;
&lt;p&gt;The Class coupling is more complex, and it also depends on the Depth of Inheritance.  I have not been able to find any solid recommendations there, but it seems that values beyond 15 to 20 should be avoided. &lt;/p&gt;
&lt;p&gt;It would be nice if the flags shown in Visual Studio Code Metrics window could have customized limits - put them into a configuration file!  First, they are fixed in code down in a method IconForMaintainabilityIndex in the CodeMetricsBranch class of the  Microsoft.VisualStudio.Metrics.Package.UI.  However, we &lt;em&gt;can&lt;/em&gt; live without yellow and red flags, as long as the appropriate levels are known. &lt;/p&gt;
&lt;p&gt;The table below summarizes this:&lt;/p&gt;
&lt;table cellspacing="0" cellpadding="2" width="457" border="1"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="82"&gt; &lt;/td&gt;
            &lt;td valign="top" width="130"&gt;Maintainability Index&lt;/td&gt;
            &lt;td valign="top" width="107"&gt;Cyclomatic Complexity&lt;/td&gt;
            &lt;td valign="top" width="136"&gt;Class Coupling&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="88"&gt;Green&lt;/td&gt;
            &lt;td valign="top" width="134"&gt;&amp;gt; 60&lt;/td&gt;
            &lt;td valign="top" width="111"&gt;&amp;lt; 10&lt;/td&gt;
            &lt;td valign="top" width="135"&gt;&amp;lt; 20&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="90"&gt;Yellow&lt;/td&gt;
            &lt;td valign="top" width="136"&gt;40 - 60&lt;/td&gt;
            &lt;td valign="top" width="113"&gt;10 - 15&lt;/td&gt;
            &lt;td valign="top" width="133"&gt; &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="91"&gt;Red&lt;/td&gt;
            &lt;td valign="top" width="137"&gt;&amp;lt; 40&lt;/td&gt;
            &lt;td valign="top" width="114"&gt;&amp;gt; 15&lt;/td&gt;
            &lt;td valign="top" width="132"&gt;&amp;gt; 20&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Note that the values applies to the method level !  &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=127385"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=127385" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/terje/aggbug/127385.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>terje</dc:creator>
            <guid>http://geekswithblogs.net/terje/archive/2008/11/25/code-metrics---suggestions-for-appropriate-limits.aspx</guid>
            <pubDate>Wed, 26 Nov 2008 03:20:49 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/terje/comments/127385.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/terje/archive/2008/11/25/code-metrics---suggestions-for-appropriate-limits.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/terje/comments/commentRss/127385.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/terje/services/trackbacks/127385.aspx</trackback:ping>
        </item>
        <item>
            <title>Hiding generated code from Code Analysis, Metrics and Test Coverage</title>
            <link>http://geekswithblogs.net/terje/archive/2008/11/10/hiding-generated-code-from-code-analysis-metrics-and-test-coverage.aspx</link>
            <description>&lt;p&gt;When I do either Code Analysis, Code Metrics or looking at Code Coverage results, I don't want to have any generated code affecting the results.  It just confuses the numbers, and I do not really care how generated code looks - it should just be invisible.  &lt;/p&gt;
&lt;p&gt;Generated code appears several places, code is generated by any of the multitude of wizards and designers in Visual Studio, or it may be generated by a 3rd part tool or generated by a self-written tool.&lt;/p&gt;
&lt;p&gt;There exist an attribute which, if attached to the class or method, is intended to hide the code from these analyses. However, it fails to do so for the Code Coverage.  The attribute is the GeneratedCodeAttribute, and it is intended to be used for any tools generated code.  See &lt;a href="http://blogs.msdn.com/fxcop/archive/2007/04/27/correct-usage-of-the-compilergeneratedattribute-and-the-generatedcodeattribute.aspx"&gt;http://blogs.msdn.com/fxcop/archive/2007/04/27/correct-usage-of-the-compilergeneratedattribute-and-the-generatedcodeattribute.aspx&lt;/a&gt; for more information on the correct usage.  It can be used both at class level and method level.&lt;/p&gt;
&lt;p&gt;However, the Code Coverage doesn't abide by these rules, as also reported in a two bug reports &lt;a title="http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=338895" href="http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=338895"&gt;http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=338895&lt;/a&gt; and &lt;a href="http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=349243"&gt;http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=349243&lt;/a&gt;.  The latter indicate they will not fix this bug,  so please go in a vote for a fix!&lt;/p&gt;
&lt;p&gt;As a workaround there are two more attributes which can be used, the DebuggerNonUserCode and DebuggerHidden attributes. The former is a combination of the latter and the DebuggerStepThrough attribute.  The DebuggerNonUserCode attribute can be used on both class and method level.&lt;/p&gt;
&lt;p&gt;By using this attribute in addition on generated code, it will not show up in the Code Coverage either.&lt;/p&gt;
&lt;p&gt;The table below summarizes this:&lt;/p&gt;
&lt;table cellspacing="2" cellpadding="2" width="400" border="1"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="72"&gt; &lt;/td&gt;
            &lt;td valign="top" width="166"&gt;GeneratedCodeAttribute&lt;/td&gt;
            &lt;td valign="top" width="152"&gt;DebuggerNonUserCode&lt;br /&gt;
            &lt;p&gt;DebuggerHidden&lt;/p&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="72"&gt;Code Metrics&lt;/td&gt;
            &lt;td valign="top" width="166"&gt;Excludes code&lt;/td&gt;
            &lt;td valign="top" width="152"&gt;No Effect&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="72"&gt;Code Analysis&lt;/td&gt;
            &lt;td valign="top" width="166"&gt;Excludes code&lt;/td&gt;
            &lt;td valign="top" width="152"&gt;No Effect&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="72"&gt;Code Coverage&lt;/td&gt;
            &lt;td valign="top" width="168"&gt;No Effect&lt;/td&gt;
            &lt;td valign="top" width="154"&gt;Excludes code&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
]]&gt;&lt;/style&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Further, Microsoft seems to have "forgotten" to add these attributes to some of their own generated code, among them is the Winform generated code. The MSDataSetGenerator adds the GeneratedCode attrbute, but not the DebuggerNonUserCode attribute. (If the Code Coverage had abided by the rules, this would not have been a problem) &lt;/p&gt;
&lt;p&gt;For Winform generated code, it is safe to add these attributes afterwards. The generated file will not be rewritten, just changed, when you add more or edit the controls. Just add them as shown below:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre class="csharpcode"&gt;        [DebuggerNonUserCode]
        [GeneratedCode(&lt;span class="str"&gt;"Winform Designer"&lt;/span&gt;,&lt;span class="str"&gt;"VS2008 SP1"&lt;/span&gt;)]
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InitializeComponent()&lt;/pre&gt;
&lt;pre class="csharpcode"&gt; &lt;/pre&gt;
&lt;p&gt;The MSDataSetGenerator is not so forgiving, since the file easily can be rewritten. However, all the classes are partial, so by adding another manual file, and using the attributes there, most of the DataSet can be removed from the Code Coverage.  Adding one dataset with one table generates a lot of classes, the code below shows what is needed to eliminate a dataset and its tableadapter for a table named ErrorLog.&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; WindowsFormsApplication10&lt;/pre&gt;
&lt;pre&gt;{&lt;/pre&gt;
&lt;pre class="alt"&gt;    [DebuggerNonUserCode]&lt;/pre&gt;
&lt;pre&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; DataSet1&lt;/pre&gt;
&lt;pre class="alt"&gt;    {&lt;/pre&gt;
&lt;pre&gt;        [DebuggerNonUserCode]&lt;/pre&gt;
&lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ErrorLogDataTable&lt;/pre&gt;
&lt;pre&gt;        {&lt;/pre&gt;
&lt;pre class="alt"&gt;        }&lt;/pre&gt;
&lt;pre&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;        [DebuggerNonUserCode]&lt;/pre&gt;
&lt;pre&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ErrorLogRow&lt;/pre&gt;
&lt;pre class="alt"&gt;        {&lt;/pre&gt;
&lt;pre&gt;        }&lt;/pre&gt;
&lt;pre class="alt"&gt; &lt;/pre&gt;
&lt;pre&gt;    }&lt;/pre&gt;
&lt;pre class="alt"&gt; &lt;/pre&gt;
&lt;pre&gt;    &lt;span class="kwrd"&gt;namespace&lt;/span&gt; DataSet1TableAdapters&lt;/pre&gt;
&lt;pre class="alt"&gt;    {&lt;/pre&gt;
&lt;pre&gt;        [DebuggerNonUserCode]&lt;/pre&gt;
&lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ErrorLogTableAdapter&lt;/pre&gt;
&lt;pre&gt;        {&lt;/pre&gt;
&lt;pre class="alt"&gt;        }&lt;/pre&gt;
&lt;pre&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;        [DebuggerNonUserCode]&lt;/pre&gt;
&lt;pre&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; TableAdapterManager&lt;/pre&gt;
&lt;pre class="alt"&gt;        {&lt;/pre&gt;
&lt;pre&gt;        }&lt;/pre&gt;
&lt;pre class="alt"&gt;    }&lt;/pre&gt;
&lt;pre&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
]]&gt;&lt;/style&gt;
&lt;p&gt;In my little test case, code coverage changed from 2,54% to 10% just by removing the DataSet1 alone. &lt;/p&gt;
&lt;p&gt;Under the Properties folder (for a WinForm app), the Resources class is decorated with both attributes (Hurrah!) (luckily since it's not partial....) whereas the Settings class only have the GeneratedCode attribute. (Why are these two different ?).  The Settings.Designer.cs file is regenerated each time you change anything in the settings designer, but it is partial, so the same trick as above with the DataSet can be used - create a new file, with the same partial class declaration, and add the DebuggerNonUserCode to it.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;In a later post I'll try to make an even more comprehensive list of which generators work and which doesn't, in this respect, and outline the workarounds for these. &lt;/p&gt;
&lt;p&gt;Hopefully - all of these will be fixed in Visual Studio 2010.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=126911"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=126911" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/terje/aggbug/126911.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>terje</dc:creator>
            <guid>http://geekswithblogs.net/terje/archive/2008/11/10/hiding-generated-code-from-code-analysis-metrics-and-test-coverage.aspx</guid>
            <pubDate>Mon, 10 Nov 2008 09:09:41 GMT</pubDate>
            <comments>http://geekswithblogs.net/terje/archive/2008/11/10/hiding-generated-code-from-code-analysis-metrics-and-test-coverage.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/terje/comments/commentRss/126911.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/terje/services/trackbacks/126911.aspx</trackback:ping>
        </item>
    </channel>
</rss>