{"id":128,"date":"2010-03-31T21:14:52","date_gmt":"2010-04-01T04:14:52","guid":{"rendered":"http:\/\/angryweasel.com\/blog\/?p=128"},"modified":"2010-03-31T21:14:52","modified_gmt":"2010-04-01T04:14:52","slug":"getting-it-right-the-second-time","status":"publish","type":"post","link":"https:\/\/angryweasel.com\/blog\/getting-it-right-the-second-time\/","title":{"rendered":"Getting it right the second time"},"content":{"rendered":"<p>I\u2019ve been working on integrating a set of code scanning tools into our build system. Test code needs to be trustworthy \u2013 when test code fails, it should indicate a product failure. More importantly, when tests pass, they better indicate that the functionality under test works. One part of increasing quality is getting rid of the coding errors that are most prone to causing test failures. This includes a basic set of fxcop rules for managed code, similar rules for native code, and specific checks for hard coded paths, hardcoded passwords, and other easy to spot things that will eventually cause false positives.<\/p>\n<p>The framework we use requires \u201chints\u201d to find the reference libraries at compile time (basically, we run fxcop against every managed assembly at build time and track a full list of errors). The hints are just a pointer to the library in the project xml file. It\u2019s a bit of a pain, but completely worth it in the end. I spent a few hours last week building a portion of the tree, reviewing the errors for the references the framework couldn\u2019t find, adding them, then verifying the additions. Lather, rinse, repeat.<\/p>\n<p>I made a ton of progress in those few hours, but stopped because it just didn\u2019t seem efficient. I was doing other work during the builds, so I felt productive, but it just didn\u2019t seem right. So, I stopped and did other work. As I look back on it, it wasn\u2019t really even a conscious decision \u2013 I just sort of mentally reprioritized that task.<\/p>\n<p>Today, for some reason, I decided to take another look. I thought about it for about two minutes and had a solution. It was so dirt simple that I\u2019m embarrassed it wasn\u2019t my first choice. Rather than build part of the source code, review the errors, find the binary, and add the hint, I took care of it all at once. When the framework couldn\u2019t find a reference, it put an error in the log file something like this:<\/p>\n<blockquote>\n<p>Could not find reference \u2013 Microsoft.Internal.Foo<\/p>\n<\/blockquote>\n<p>It printed one of these for every reference it couldn\u2019t find, so I just built everything \u2013 and while it was building, I wrote a script that would parse out the reference name, look for the binary on disk, normalize the paths, remove the duplicates (multiple projects will share references), then add the appropriate xml to the project file. Total time on task was about 20 minutes and it worked perfectly.<\/p>\n<p>The point of all this is that I realize that I do stuff like this all the time. I often dig into a problem, pause (or leave), and <em>then<\/em> come up with an optimal solution. Part of me thinks that I should recognize the optimal solutions the first time, but another part of me wonders if I\u2019d be able to come up with good solutions if I didn\u2019t get my hands dirty first. I\u2019ll pay more attention and let you know how it goes.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I\u2019ve been working on integrating a set of code scanning tools into our build system. Test code needs to be trustworthy \u2013 when test code fails, it should indicate a product failure. More importantly, when tests pass, they better indicate that the functionality under test works. One part of increasing quality is getting rid of&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[1],"tags":[],"class_list":["post-128","post","type-post","status-publish","format-standard","hentry","category-allposts"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/angryweasel.com\/blog\/wp-json\/wp\/v2\/posts\/128","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/angryweasel.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/angryweasel.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/angryweasel.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/angryweasel.com\/blog\/wp-json\/wp\/v2\/comments?post=128"}],"version-history":[{"count":0,"href":"https:\/\/angryweasel.com\/blog\/wp-json\/wp\/v2\/posts\/128\/revisions"}],"wp:attachment":[{"href":"https:\/\/angryweasel.com\/blog\/wp-json\/wp\/v2\/media?parent=128"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/angryweasel.com\/blog\/wp-json\/wp\/v2\/categories?post=128"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/angryweasel.com\/blog\/wp-json\/wp\/v2\/tags?post=128"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}