This post originated from an RSS feed registered with .NET Buzz
by Scott Hanselman.
Original Post: DLL Hell - redux?
Feed Title: Scott Hanselman's ComputerZen.com
Feed URL: http://radio-weblogs.com/0106747/rss.xml
Feed Description: Scott Hanselman's ComputerZen.com is a .NET/WebServices/XML Weblog. I offer details of obscurities (internals of ASP.NET, WebServices, XML, etc) and best practices from real world scenarios.
Patrick
Cauldwell said something very wise today at work. Here's the gist:
Sure, there's no more DLL Hell for the end user. It's that they've
made it hell for the developer.
It was immediately funny, but a few hours later, it was profoundly true.
He and I are working on a really cool subsystem for our developers that offers a them
clean SOA.
As an aside, it also uses NAnt 0.8.4 for its builds. I know I said I was doing command-line
builds with DevEnv, but both Patrick and Chris
Kinsman insisted I give it another look. I was HUGE into NAnt a year
ago, but got lazy and floated away. I'm back with a vengance. The mess
of -contribs and bugs is gone and it's fantastic. It includes a whole series
of great new Tasks.
My favorites are foreach, nunit2 and
the invaluable solution task.
I'm also using nunit2report which
is great, but needs to support multiple input files.
Anyway, so this build of NAnt uses and includes assemblies for log4net and NUnit 2.1.3.
I also use log4net and have referenced NUnit 2.1.4 in our project. We automated
the entire build: codegen>build>test>report>email results. We have
a bootstrapper that gets the project into an empty dir and forks to the build file
that just came out of CVS. It's gloriously command-line and marginally g$(Rube
Goldbergian). ;)
However, a few weird things happened. First, these NAnt binaries were compiled
on the 1.0 framework, but the NAnt.exe.config was set to allow it to run on Framework
1.1. However, the lib directory for NAnt had MULTIPLE directories (clever) with
different versions of log4net, NUnit, etc, in each directory (frustrating).
I didn't notice this until NAnt tried to run the tests. NAnt loaded a non-strongly-named
NUnit 2.1.3, and by the time my tests tried to request my strongly named 2.1.4 I was
getting all kinds of binding errors and stuff. Same thing happened when my non-strongly-named
build of log4net (compiled on 1.1 as version 1.0.13704 something) tried to load into
the process space of NAnt's version of log4net (compiled on 1.0 as version 1.0.13704
ALSO).
Needless to say, this all sounds obvious after the fact, but I needed to sync up my
versions. Certainly I could strongly name things and GAC them, but that kind
of is orthoganal to the goal of a build-anywhere-relative-paths-xcopy kind of project.
So, the easiest and safest thing to do in order to maintain my goal of minimal dependancies
was to rebuild NAnt on 1.1 with my preferred minor versions of log4net and NUnit via a
shared lib.
So, back to Patrick's point. The CLR offers some amazing improvements over COM-style
and LoadLibrary/GetProcAddress DLL Hells. Truly. We have side-by-side
assemblies, the GAC, and strong naming. However, it does put increasing logistical
pressure on the developer to define appropriate policies and procedures to balance
ease of development with ease of deployment.
It takes some serious thought to plan this stuff, and arguably it's not possible to
get it right the first time. Or the third. While the underlying support is there
in the CLR, certainly the complex issues around dependancy management, both at compile-time
and run-time are not going to be solved anytime soon with a nice Visual Studio.NET
Add-In. "File|New|Enterprise-Wide Dependancy, Version Control, and
Deployment Management Project", anyone?