Saturday, September 13, 2008

How to reference DLL’s in your .Net projects, don’t assume anything

“How great is this I just found this cool library; it fits perfectly in my current project, it even comes with an installer so I can reference it straight away?” So how are you going to provide this to your team members? “Well we have a shared folder that contains all our third party installers.”

What is wrong with this scenario?

Well every time you get a new developer on your team you have to make sure that he has all the third party libraries installed, and make sure that they are of the correct version. If you have got all the installers placed together than this is not the worst thing, but in reality you are probably missing one or two, or you don’t exactly know what is required, this is not your only project is it?

So let’s say you got the new guy up and running, it took both of you about half an hour just to get the source to compile. The new guy has to fix a bug and sees there is an update for library xyz. This update is exactly what he needs, so he downloads it installs it, compiles the code and checks in the changes. Now suddenly all other developers who updated their code need the new library to be able to compile. But which version did the new guy actually use; he went home to take an early weekend. Your Continuous Integration process also immediately stopped working because the new guy didn’t install the new version on there either. Didn’t we tell him to do that?

That’s what’s wrong.

What to do about it? Well create a folder “Libraries” in your solution and place all the needed third party libraries in there. And I basically mean everything that doesn’t come with the default .Net Framework installation. Then create absolute references to these libraries (Add reference – Open Browse tab – Find your “Libraries” folder – Select the DLL’s to include). Check-in the changes including all third party libraries, you are using a version control system right? Now when ever, where ever you check out your code you can instantly compile it. One quick way to get all the needed DLL’s is to Publish the solution, then just copy every non project DLL into the new “Libraries” folder.

But I have an ASP.Net website project and don’t have a reference folder or even a project file in my project. I really dislike the decision of Microsoft to provide projects without actual project files. In that case I would suggest using a Web Application project and include all needed files and libraries in there manually.

So the lesson is: “Don’t assume everybody is using the same DLL version, make sure everybody is using the same DLL version”.

5 comments:

Anonymous said...

Totally agree! We've basically done the same thing. Have a 3Party folder in source control for this. Except from some libraries that's in the GAC which is a prerequisite for all dev machines (Infragistics and DevExpress). This also (of course) work for many solutions. We have about 30-40 solutions (.sln) and it works great. We still stick with project ref's though for our own projects. Got burned in the beginning of the project with this and have not gone back since. Bad thing is of course that compiling takes a lot of time. Any experience with this?

Mark Nijhof said...

I would like to argue also keeping the Infragistics and DevExpress libraries in the third party folder. Why did you choose not to do so?

In the bigger projects we have had multiple solutions that each builds their own library. Other solutions that needed those libraries would reference the compiled DLL's not the project files. One of the things we did is to create another folder that would hold our own libraries, "BuildLibraries". This folder is also under source control. Solutions will only trigger a new build when an actual change was made, the generated DLL's would go into the "BuildLibraries" folder and changes are being checked-in. Unit tests would guarantee the proper working of the libraries. If someone is making an actual change to the API of the libraries, than he should verify all the usages before committing, which would theoretically be the only time a full rebuild is needed. So in other words we would consider our own generated libraries as third party too.

I am sure you would be able to split up your current solutions into different builds, grouped by functionality or responsibility. I would like to hear what problems you encountered.

Anonymous said...

Thanks for your input Mark. Regarding Infragistics and DevExpress it was because of documentation, vs integration etc... We could have put them into 3part, but would probably had to install other func anyway.

Regarding internal dll's you're describing more or less what I'm thinking :) The reason why we've not headed in that direction, is because of history and prioritization. 3-4 years back we didn't have the reliable build server as we do today, so relying on a network folder with updated dll's was not an option. Today however that shouldn't be a problem. I'll think that'll be my first task when I get back from paternity leave :) If I can wait... :)

Anonymous said...

In my previous comment I didn't expect my name to be displayed as blog... Hmmmm... Sorry for using your blog as openid testing ground :)

Mark Nijhof said...

Hehe well don't worry about it :)

As for the documentation issue, why not include that in your source control too. I like to have the following folder structure:

trunk\[project name]\
....\documentation\
....\source\
....\libraries\
....\buildlibraries\

Documentation would hold our own produced documentation but also third party documentation.

Also even if you want to have the documentation and examples and such on each machine, I would still copy the needed DLL's into the "Libraries" folder and reference them from there. Your project will prioritize DLL's found in the local bin folder over the GAC so they can live side by side.

Doing this will eliminate any possible problems. F.ex. one guy has been playing with the latest version of the control just to see what it could do, well hod do you make sure he is not using new functionality by accident next time he is working with the source code?

And last but not least, no installers needed on the build server.

Regarding the comment "so relying on a network folder with updated dll's" I wouldn't recommend using a network share, just place them in source control; a get latest version should suffice.