Whilst hacking together a prototype console application and then reusing it within a WinForms app, it struck me that the dynamically linked library as far as the (.NET developer is concerned), seems somewhat obsolete.
There appears nothing that can be done with an assembly in the form of a DLL that can’t be done with an EXE. In fact, the only reason I seem to create libraries in this way is because ‘someone once told me to’ plus the test runner I use seemed to require it.
If we look at the Java and C++ worlds, things seem to be slightly different. By default, Java does not appear to differentiate between library and executable code in its default distribution or package format: the JAR. A JAR file can be executed by the JVM so long as it implements the correct interface just like a Windows EXE.
In the C++ world, things seem even looser, as how you compile and package your code seems to be platform dependent (.exe, dll, lib, tlb, ocx, etc.) and the unit of re-use is even finer-grained.
So, let's look at some of the ways in which re-use is achieved:
Code relating to deployable components and that relating to common components are separated by folder, workspace or even a separate repository within the source control system. At compile time, code re-use is achieved by directly compiling that common source code as you compile your deployable. Artefacts can either be a single executable or library or any number of these combined.
There may be slight variants of the above, but essentially they will either be using pre or post compile time sharing. With post compile seemingly preferred in most instances I have encountered. Note, there is nothing about either strategy that forces us to choose one binary output over another. But I do see many open source projects where it is feasible to build your own library by simply picking the class files you need at build time and more than one client that uses source control sharing and still builds DLL components.
- A single solution file (or sometimes workspace) to build a single, versionable deployable component, where a ‘deployable’ component can be a single long running service or user tool, e.g., client side GUI or website. A versionable component means that any change to that component’s code increments the version (and so is usually derived from the source control’s particular revisioning method). Such a component may depend on one or common components that it shares with other deployables.
The notion of a common component is code that is to be re-used. Generally, this is moved to a common area within source control. It is built separately from the deployable component and therefore has its own solution file and suite of automated tests. Importantly, it has its own separate version number from any other component. Once compiled, we can share them with deployable components using source control (i.e., checking them in somewhere) or using a package manager such as nuget or maven.
- The build system defines the deployable component and source control is used to share code.
SO after a little bit of thought, I did ask the question:
But most answers assumed I didn’t understand there was a thing called an assembly and so missed the point. One person did mention ilmerge and after further questioning, admitted that his opinion only really boiled down to load and start up times. Not one mentioned compatibility, which suggests that most .NET developers do not take that into consideration and aren’t designing for it.
Perhaps there are some underlying reasons why it’s conventional (or idiomatic) to build a DLL. Or perhaps most of us are following a cargo-cult!