Software Is Hardwork

ISimplicityAffinative: The endless pursuit of anti-complexity.
The technology-centric blog of D. P. Bullington.

Email D. P. Bullington View D. P. Bullington\ Follow D. P. Bullington on Twitter Get Software Is Hardwork code on CodePlex

Blog Post(s)

Enable Stack Trace Line Numbers in ASP.NET and SharePoint and GAC-ed Assemblies
Tuesday, February 2, 2010

When exceptions occur in your ASP.NET or SharePoint custom code, if the symbols cannot be located then line numbers and file names will be absent from the stack trace. This can be a burden in environments when assemblies are placed into the global assembly cache (GAC); this is not an issue on traditional ASP.NET ~/bin local assembly deployments however. Using the following registry script (at your own risk), stack traces will come alive with more detail.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]
"_NT_EXECUTABLE_IMAGE_PATH"="c:\\MyCustomSymbols;c:\\windows\\symbols"
"_NT_SYMBOL_PATH"="c:\\MyCustomSymbols;SRV*c:\\windows\\symbols*http://msdl.microsoft.com/download/symbols"

Replace the c:\MyCustomSymbols path with any path you would like to store you custom symbols (PDB's generated in debug or release build). The above also assumes the use of the Microsoft Symbol Server. As a matter of a well architected automation strategy, I make it a point to include the PDB's in the output of my packaging scripts for all ASP.NET and SharePoint solutions. This way, the resultant ZIP file for a given release contains all relevant artifacts including PDB's (even for release builds).

You must recycle IIS (iisreset /noforce) in order for this to take affect. If you are logged into the target machine and plan to debug locally, you must log out and log back in.

One thing of note, if you have the solution open on the server (e.g. you are developing and debugging on the target machine, there is no need for this. Visual Studio is now smart enough to locate symbols in the solution and use.

Please see Optimal Debug Settings for VS.NET 2008 SP1 for additional information.

Optimal Debug Settings for VS.NET 2008 SP1

Out of the box, VS.NET 2008 SP1 debugger options cripple you from debugging efficiently and effectively. I have compiled this list of options which will allow a more pleasant debugging experience.

Click the Tools menu and select Options. In the Options dialog box, expand the Debugging node and select General.

[_] Ask before deleting all breakpoints
[X] Break all processes when one process breaks
[_] Break when exceptions cross AppDomain or managed/native boundary
[X] Enable address-level debugging
    [_] Show disassembly if source is not available
[X] Enable breakpoint filters
[_] Enable the Exception Assistant
    [X] Unwind the call stack on unhandled exceptions
[_] Enable Just My Code (Managed only)
    [_] Show all members for non-user objects in variables windows (Visual Basic only)
    [X] Warn if no user code on launch    
[_] Enable .NET Framework source stepping
[_] Step over properties and operators (Managed only)
[X] Enable property evaluation and other implicit function calls
    [_] Call ToString() on objects in variables windows (C# and JavaScript only)
[_] Enable source server support
    [_] Print source server diagnostic messages to the Output window
[_] Highlight entire source line for breakpoints and current statement
[X] Require source files to exactly match the original version
[_] Redirect all Output window text to the Immediate window
[_] Show raw structure of objects in variables windows
[X] Suppress JIT optimization on module load (Managed Only)
[X] Warn if no symbols on launch (Native Only)
[X] Warn if script debugging is disabled on launch

I will update this for Visual Studio 2010 when it releases to manufacturing.

Stop Exposing Your Privates
Tuesday, January 19, 2010

Microsoft has done it again with the Generation of Private Accessors (Publicize) and Code Generation thereof feature for Visual Studio 2010. They are trying to make it even easier to expose protected or private type members in the name of "testing".

Publicize is the ability to take internal application programming interfaces (API) and create public counterpart API that you can call in your tests, which would in turn, call into the internal APIs of your product. This comes in the form of a stand alone executable, or can be seen when using code generation to create test method stubs of internal or private APIs.

This feature did not make the final cut for 2010 RTM thankfully. As I warned in a previous article, access modifier subversion is plain wrong, even under the thinly veiled attempt to make testing easier. If you cannot exercise all code paths via the type's public interface (or protected interface if dealing with subclassing), then you either: a) have dead code which needs review; b) have guard code which should never execute under any circumstance but should remain as a countermeasure; c) have a faulty testing strategy (e.g. you are unit testing when an integration test is called for); or d) have a poorly designed type and should consider refactoring.

Personally, I hope to never see the feature surface in any future release and instead spend those development resources on more compelling Visual Studio features like performance of the IDE, et. al.

A Conversation on Software Testing
Monday, January 11, 2010

Recently, I had an instant messenger conversation with my good friend Paul Laudeman regarding software testing, integration testing specifically. The following is the transcript from this conversation. Thanks to Paul for allowing me to share.

Paul Laudeman: So tell me, how do you feel about integration testing including database testing?

Daniel Bullington: Well let me step back. I feel that correct unit testing is above all else, key in any testing strategy.

Paul Laudeman: I agree with that.

Daniel Bullington: This includes correct unit testing of persistence objects <-> database with mocking etc. (that’s part one of my answer).

Paul Laudeman: Right.

Daniel Bullington: Part two: Then, integration testing is important too, but a well defined strategy for generating test data and resetting to good state is essential. This presupposes that your code base is well architected enough to facilitate both distinct testing types.

Paul Laudeman: Which I've seldom ever found to be the case but that's another story.

Daniel Bullington: In that case, you are left with "unitegration testing" - unit + integration.

Paul Laudeman: So what about testing a “feature” slice from say, your business logic all the way through to persistence logic and loading from the database where you script out your database objects and push the data in and out of the database?

Daniel Bullington: Well, integration testing is a layered phenomenon, whereas unit testing is a compartmental phenomenon. So you would in a perfect would test integration between persistence objects <-> database; then domain layer/business objects <-> persistence objects, presentation logic <-> domain/business layer...you see the pattern.

Paul Laudeman: Right, that's what I’m getting at, integration testing, between more than just one tier and/or layer, to include an external system, such as a database. In other words, to prove out that your persistence logic actually works; not that you were just lucky and got the mocking code right.

Daniel Bullington: I think you are using the conventional but incorrect viewpoint...when you say "between more than just one tier and/or layer" - you really mean integration between tiers and/or layers (and any sub tiers and/or via guilt by association). It’s incorrect to say "all" because for instance, your domain layer/business layer has no clue what is in the persistence layer (e.g. is there even a database or is it web service)...see what I’m saying?

Paul Laudeman: Agreed.

Daniel Bullington: By the sheer fact you are integration testing domain/business objects <-> persistence objects, you are testing the database too, but only as an acceptable side effect. It’s about separation of and targeted testing concerns.

Paul Laudeman: Ok, then how would we go about testing the persistence objects <-> database, or should we?

Daniel Bullington: Yes.

Paul Laudeman: That's what I was trying to ask. Sorry for the roundabout way to get to it.

Daniel Bullington: It’s like asking “Why should use interfaces and mock out dependencies?” It’s the same rationale - in a roundabout way. You integration test your persistence objects <-> database separately from the integration testing between domain layer/business objects <-> persistence objects. There can and will be nuances which can change the testing dynamics...even thought 99% of the time, if you integration test between the domain layer/business objects <-> persistence objects, you are exercising the database as well. My thought is that each integration point should be independently tested so you can also have a suite targeted to that integration point. This is again, all this in a perfect world - infinite time, people, and money.

Paul Laudeman: Absolutely agreed.

Daniel Bullington: I guess you could call me a software testing snob or "realistic fanatic".

A Quick Stroll Down Polymorphic Lane
Monday, December 14, 2009

A programmer generally learns about polymorphism as one of the reasons that make object oriented programming so powerful. In C#, every type is polymorphic in terms of System.Object, plus in the context of interface implementation and/or class inheritance. Polymorphic in its purest and most general sense is much more than meets the eye. Let dig deeper into this subject and learn some surprising polymorphic constructs you may already be using an not knowing it.

Polymorphic behavior in programming languages comes in two main varieties: universal and ad hoc. Universal polymorphism has two sub-varieties: parametric and inclusion. Ad hoc polymorphism also expresses two sub-varieties: overloading and coercion. Universal/parametric polymorphism is accomplished when a function performs with any type. Universal/inclusion polymorphism is achieved when, for instance, a subclass is used in place of a superclass. Ad hoc/overloading polymorphism leverages the same operator for differing types, such as the add operator for a point type and a rectangle type. Ad hoc/coercion polymorphism performs a conversion to an expected type, for example, from Double to Int32. The line between overloading and coercion can easily get blurred depending on the context.

The defining difference between universal and ad hoc polymorphism is that universal polymorphism will execute the same code whereas ad hoc polymorphism will execute different code at runtime. Fun stuff.

Hampton Roads .NET Users Group: SharePoint Antithesis - A Case Study in Pragmatic Software Architecture and Engineering Processes
Friday, December 11, 2009

I presented "SharePoint Antithesis - A Case Study in Pragmatic Software Architecture and Engineering Processes", discussing how a simplification of the software architecture and engineering processes allowed an ASP 3.0 to SharePoint/MOSS Enterprise Content Management migration project to achieve an unprecedented 5x gain in productivity while generating a successful end solution which is maintainable, scalable, and manageable, at the Hampton Roads .NET Users Group this past Tuesday evening. It went quite well and I have a nice number of attendees to the talk. Good questions too!

NOTE: Due to my own mis-marketing, it was not clear that this was quite relevant to .NET developer audiences.

The PDF conversion of the slide deck can be had here:
SharePoint Antithesis - A Case Study in Pragmatic Software Architecture and Engineering Processes.pdf

The sample code demonstrated during the talk can be had here:
Contoso Sample (HRNUG 2009-12-08).zip

MP3 podcast:
SharePoint Antithesis - A Case Study in Pragmatic Software Architecture and Engineering Processes (HRNUG 2009-12-08).mp3

Thanks to all those who organized the affair and to all those who attended my talk.

Presenting at Hampton Roads .NET Users Group - 12/08/2009
Monday, November 16, 2009

SharePoint Antithesis – A Case Study in Pragmatic Software Architecture and Engineering Processes

Consider if you will, an ASP 3.0 to SharePoint/MOSS Enterprise Content Management migration project which used many of the technologies available in the stack: Publishing features, Business Data Catalog, Single Sign-On, custom SharePoint lists/document libraries, custom web parts, custom site branding, custom site metadata, and many other “enterprisey” whiz-bang gizmos. Now imagine that after many burned clock ticks of active development, barely a scratch was made in the feature set. This discussion will explore how a simplification of the software architecture and engineering processes allowed the project to achieve an unprecedented 5x gain in velocity while generating a successful end solution which is maintainable, scalable, and manageable.

Information, registration, and directions...

King Todd's Whiteboard Laws
Tuesday, November 10, 2009

When SHTF, it is always:

  1. Configuration
  2. Security
  3. Source Control
  4. Bad Data
  5. Silverlight Databinding
  6. Or a combination of the above

Speaking Enagements

  • 11/18/2010 | Charlottesville .NET Users Group | Charlottesville, VA | Topic TBD
  • 09/14/2010 | Hampton Roads .NET Users Group | Cheaspeake, VA | Topic TBD
  • 07/01/2010 | Richmond .NET Users Group | Richmond, VA | Topic TBD
  • (past) 12/08/2009 | Hampton Roads .NET Users Group | Cheaspeake, VA | SharePoint Antithesis - A Case Study in Pragmatic Software Architecture and Engineering Processes
  • (past) 10/04/2009 | Richmond Code Camp 2009.2 | Richmond, VA | Soothing the Pain Points: Data Access, Validation, Rules, UI, Presentation, et. al
  • (past) 07/23/2009 | Charlottesville .NET Users Group | Charlottesville, VA | Debugging on the Windows Platform
  • (past) 05/23/2008 | NoVa CodeCamp 2009.01 | Reston, VA | Going Proxy-less - The WCF Proxy Factory
  • (past) 04/25/2009 | Richmond Code Camp 2009.1 | Richmond, VA | Software Programmer to Software Engineer: Concepts to Span the Divide
  • (past) 02/05/2009 | Richmond .NET Users Group | Richmond, VA | Debugging on the Windows Platform
  • (past) 10/04/2008 | Richmond Code Camp 2008.2 | Richmond, VA | Going Proxy-less - The WCF Proxy Factory

Blog Archive

Post Labels

.NET (64) .NETv4.0 (3) ACID (1) ActiveDirectory (1) ADF (2) Affiliate (1) Agile (6) AJAX (1) Allocator (3) Analysis (1) AOP (4) ASP.NET (6) ASP.NET MVC (1) Assembly (2) BadIdeaPile (1) BagOfBolts (5) Blogger (1) Books (2) BuildMgmt (8) C# (46) ChoDNUG (1) CLR (1) CLRv4.0 (2) CMP (1) CMS (2) CodeCamp (2) COM (1) Conversation (1) Coverage (1) CUI (1) Database (2) DDD (1) DeadFxs (1) Debugging (9) Design (4) DevAuto (3) DevCfg (1) Development (118) DI (6) DiffMerge (1) Domain (1) DTfW (2) EclipseIDE (1) ECM (1) EntityFramework (1) Estimating (1) FileShare (1) Frameworks (7) GAC (2) Google (1) Hardware (2) HRNUG (1) Humor (6) IIS (4) ILDASM (1) Impersonation (2) InstallError (1) IoC (6) KingTodd (1) LinkedIn (1) LINQtoSQL (2) MarketingHype (1) MBUnit (1) Mentoring (22) Metadata (1) Microsoft (7) MOSS2007 (5) MSBuild (2) MSIL (4) MSSCCI (2) NAnt (2) NCore (2) NCover (1) NDatabase (4) NetUse (1) NHibernate (2) NoVaCodeCamp (2) NTSD/CDB (2) NUnit (1) Observation (2) Office (2) OOD (7) OOP (6) OpenSource (14) Opinion (19) Personal (3) PMP (1) Polymorphism (1) PowerPoint (1) PowerShell (2) Presentation (3) Process (4) ProjectManagement (2) PublicKeyToken (1) QA (2) RDNUG (1) Reflection (2) Registry (2) Resharper (1) Reversing (2) RichmondCodeCamp (5) SCM (11) Scrum (5) Security (2) Series (3) Server2008 (4) ServicePack (1) SES (7) SharePoint (7) Silverlight (1) SoC (3) Software (49) SoftwareIsHardwork (17) Speaking (7) SQL (2) SSO (2) StrongName (2) Suite2008 (9) Suite2010 (1) SwEng (19) TechBlunder (1) Testing (14) Thread (3) Tools (8) Troubleshooting (10) Twitter (3) Types (2) UAC (1) UIP (1) Vault (2) VB6 (1) VC (1) Vista (3) VisualStudio (15) VSIP (2) VSTS (1) WCF (4) Web (4) WebForms (1) Win32 (3) WinDBG (3) WindowsIdentity (3) WinForms (1) WIT (1) Workhorse (1) WoW64 (1) WPF (1) WSS3 (2) x64 (2) x86 (2) xUnit (1)

Disclaimer

© D. P. Bullington, all rights reserved. Everything posted on this blog is my personal opinion and does not represent the views of my employer nor serves to infringe on the sovereignty of any nation.