{"id":3201,"date":"2015-02-25T13:00:53","date_gmt":"2015-02-25T13:00:53","guid":{"rendered":"http:\/\/writeasync.net\/?p=3201"},"modified":"2015-02-25T05:56:30","modified_gmt":"2015-02-25T05:56:30","slug":"binary-explosion","status":"publish","type":"post","link":"http:\/\/writeasync.net\/?p=3201","title":{"rendered":"Binary explosion"},"content":{"rendered":"<p>How many binaries do you need for a .NET project? How many is too many? Does it really matter?<\/p>\n<p>I&#8217;ll admit I have a strong aversion to the phenomenon which I&#8217;ve dubbed &#8220;binary explosion&#8221; &#8212; tens (or hundreds!) of tiny assemblies. In each of the dozen or so cases I&#8217;ve seen, there was never a good reason to have ended up with this many separate libraries and it was always a consequence of unchecked organic growth. How can we defuse this binary bomb? Let&#8217;s start with some guidelines about when a binary boundary makes sense.<\/p>\n<p>If a component has a separate deployment\/versioning lifecycle, then it belongs in a separate assembly. This case is pretty self-explanatory and will never run afoul of my usual binary parsimony. If you can (or must) update A without updating B, then you need to split them into discrete units (e.g. &#8220;A.dll&#8221; and &#8220;B.dll&#8221;).<\/p>\n<p>Use separate assemblies for public and private dependencies. If you are building a server component which has an associated client library, obviously you don&#8217;t want to ship the back-end logic to the front-end consumers. It makes perfect sense to have &#8220;Contoso.Server.dll&#8221; and &#8220;Contoso.Client.dll&#8221;. It <em>does not<\/em> however make sense to have 10 client DLLs that all must be present for an app to work properly (&#8220;Contoso.Client.Common.dll&#8221;, &#8220;Contoso.Client.Data.dll&#8221;, &#8220;Contoso.Client.Net.dll&#8221;, &#8230;). There are very few legitimate use cases where you need this level of binary separation. It just causes annoyance to the poor user that has to remember to add a half-dozen DLL references or else &#8220;Hello World&#8221; fails to run. Look to the .NET Framework itself for inspiration and be amazed at the number of useful apps you can write by bringing in just &#8220;System.dll&#8221; and &#8220;System.Core.dll&#8221;.<\/p>\n<p>Entry points generally need a distinct binary. This would apply to things like an EXE for a console app, an assembly containing an <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/azure\/hh180152.aspx\">Azure role entry point<\/a>, and so forth. However, even here there are some options. Maybe you don&#8217;t need a full-fledged MyAppTool.exe if you can build a <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms714395(v=vs.85).aspx\">PowerShell cmdlet<\/a>. This might in fact be <em>more<\/em> attractive than a vanilla EXE to a savvy user who needs a first-class scripting experience.<\/p>\n<p>If you need strong separation between certain dependencies, a binary boundary could be valid. GUI interaction logic is a common case, but really this could apply to any sufficiently complex external dependency. For example, if parts of your system depend on <a href=\"http:\/\/azure.microsoft.com\/en-us\/documentation\/services\/storage\/\">Azure Storage<\/a>, you may want these service bindings to live in a separate library than the &#8220;core&#8221; DLL (which perhaps contains only framework dependencies unencumbered by externals). Doing this right means defining good abstractions in your core library (e.g. &#8220;interface IBlobStore&#8221;) which the externally focused library can fill out with the concrete details (e.g. &#8220;class AzureBlobStore : IBlobStore&#8221;).<\/p>\n<p>Finally, test code generally goes in a separate library from product code. Almost everyone does this already but I include this for completeness. I do want to stress that <strong>you must not go crazy here<\/strong>. It is hardly useful or practical to have separate test libraries for each feature under test (sadly enough, I <em>have<\/em> seen this happen). Namespaces are great for logical separation and test grouping, as needed.<\/p>\n<p>One last note about performance: there is a fixed cost associated with every assembly, especially in compilation and <a href=\"http:\/\/blogs.msdn.com\/b\/junfeng\/archive\/2004\/02\/23\/78139.aspx\">runtime loading<\/a>. It is much faster to compile one relatively large assembly than 100 medium-sized ones. One potential drawback is the <em>recompilation<\/em> cost &#8212; finer-grained dependencies mean fewer things to rebuild when a small isolated change occurs. In my experience, though, I haven&#8217;t really seen this &#8220;benefit&#8221; shine so brightly in contrast to the many clear drawbacks of binary explosion.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How many binaries do you need for a .NET project? How many is too many? Does it really matter? I&#8217;ll admit I have a strong aversion to the phenomenon which I&#8217;ve dubbed &#8220;binary explosion&#8221; &#8212; tens (or hundreds!) of tiny&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[91],"tags":[],"class_list":["post-3201","post","type-post","status-publish","format-standard","hentry","category-design"],"_links":{"self":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/3201","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3201"}],"version-history":[{"count":0,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/3201\/revisions"}],"wp:attachment":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3201"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3201"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}