One of the hard rules for me in software development is DRY: Don’t Repeat Yourself. It’s about removing duplication, whenever it is found, at all levels of the source code.
The primary reason for adhering to the DRY principle is this: in a system where any piece of code may or may not be duplicated somewhere else, a gigantic burden is put on every developer of the team. That is because fixing an error somewhere does not mean the general problem with that algorithm is solved – after all the algorithm may be located at any number of other locations in the system.
In a system with lots of duplication only developers with “complete” knowledge of the source code base will be able to work with it successfully. Many developers believe they know all the corners of their source code base. I’m not one of them.
But removing duplication is not trivial. It often requires large refactorings of the code, an operation of great risc if the code lacks automated tests.
Today I was faced with creating a 3D mesh viewer. Since the viewer is part of a larger WinForms application, it felt natural to create a Class Library with a Form and a simple API to be called from the host application.
Since I built a similar 3D application, which I’ll call 3d line connector (users could build connection lines between polygons with it) I thought of reusing as much as possible of the classes & algorithms from that project. Problem was that project was a single Windows Application (.NET EXE). Even though it is possible to reference EXE files (they are assemblies just as .NET DLL’s), the gut feeling was that I wanted to break out the necassary and sufficient files into a separate DLL.
So I set out to perform this refactoring of the 3d line connector. To begin with I moved the relevant classes into a separate project folder in the Solution Tree. That way I could use Shift+F12 to navigate around the code and find exactly what classes were dependend on each other and move them to that folder.
Step two was to create a separate Class Library and move the content of the subfolder there. After adding the necessary references between the EXE file and the DLL, everything was fine.
The last step of the separation was renaming the namespace to fit the new location. That rendered some compilation errors, which was removed by some Ctrl+.+Return combos.
Then I realized the following: to use this new Class Library in the new Mesh Viewer project, I had to make a copy of the built DLL from this solution. Reason being I didn’t wan’t the code on two different locations in the Subversion tree where all our projects are backuped. Having the source code backed up in two different locations in the central repository would break the DRY principle.
By then everything started getting so technical and complicated I decided to “back up” slightly and think about what general problem I was trying to solve.
What I was looking for was shared code, in the following meaning: when working on one of the projects, whenever I fixed something in the shared part of the code, it would be reflected in the other project. That is the whole point of DRY: applying a patch at one point in the system, spreads the fix to every other “use” of the algorithm.
That got me thinking that the shared code (library) was really a project in it’s own right. So it should be removed from the line connector project altogether, and stored separately in the subversion tree.
Then the mesh viewer aswell as the line connector could have a hard copy of the built DLL file added as a physical file in the SVN archive.
Logically that felt a lot cleaner – after all the common code didn’t belong any more to the line connector project than the mesh viewer project.
But I’m still at a loss of how to achieve the automatic updating of the physical DLLs practically. However, if we view the common code as a third party dependency, there should not *be* any automatic updating (that is a manual task for good reasons – otherwise our computers would be constantly updating themselves at all levels. Uhum. Well, they actually do just that quite often.)
How do you manage shared code libraries under a team setting in Windows/.NET/SVN?