Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I mix technologies within assemblies?

I have a medium-sized project, which implements about 20 or so different concepts. At the beginning, I chose to organize my assemblies based on conceptual layers, like so:

MyProject.Domain.dll (References System.Data.Linq, etc.)
  \ConceptA\
  \ConceptB\
  \ConceptC\
  \...\

MyProject.Presentation.dll
  \ConceptA\
  \ConceptB\
  \ConceptC\
  \...\

MyProject.WinForms.dll (References System.Windows.Forms, etc.)
  \ConceptA\
  \ConceptB\
  \ConceptC\
  \...\

MyProject.App.exe (References all the above)

I've recently read in a DDD book that I should group my assemblies based on the domain concept it represents, rather than the technology layer, like so:

MyProject.ConceptA.dll (References System.Data.Linq, System.Windows.Forms, etc.)
  \Domain\
  \Presentation\
  \WinForms\

MyProject.ConceptB.dll
  \Domain\
  \Presentation\
  \WinForms\

MyProject.ConceptC.dll
  \Domain\
  \Presentation\
  \WinForms\

MyProject.App.exe (References all the above)

I don't have enough experience to judge the two approaches in the long term. I want to strike the best balance between complexity and flexibility. I have a few concerns that make me feel ambivalent:

  • Grouping by concept makes it easier to find my code, since it's all in one place.
  • Grouping by technology makes sure I don't call MessageBox.Show from my domain layer.
  • I will eventually switch out the data access and presentation technologies.
  • At the end of the day, all the assemblies will be referenced by the main application anyway.
  • When grouped by concept, where will the tests go? Won't I have to put them in separate assemblies so they don't ship with the program?

In your experience, which is the best approach?

like image 982
Alex J Avatar asked Oct 10 '22 18:10

Alex J


1 Answers

TL;DR: You should be doing both, but don't split your project up into multiple assemblies just for the sake of it. By splitting your assemblies down to reusable components you will end up using a combination of both methods where appropriate.


Firstly, I'd say that depending on the size of your project there may not be any need to separate either concepts or layers our into separate assemblies - the advantages of separating out your code into separate assemblies is twofold:

  1. Allowing other assemblies / applications to make use of your code by referencing your assembly
  2. Reducing the size of large assemblies by splitting into many smaller assemblies

If you don't have any need for either of those two (and you wont in the future) then keep your life simple and just bung everything into one assembly.


Secondly, the primary reason for separating code out into separate assemblies is to re-use that code - for example if you have a piece of processing logic being used in a Windows Forms application, separating that out into a separate assembly lets you re-use that logic in say a console or web application. For this reason I usually find that the best way is to separate on concepts, for example:

Company.Project.Concept.dll

Where "Concept" is something that you want to re-use, be it a set of common Windows controls or some data access logic.

Note that when re-using a concept its fairly rare to want to re-use all conceptual layers of that concept (Domain / Presentation / WinForms). Normally either your concept only consists of 1 layer (e.g. some form of processing), or when re-using that concept you are only interested in 1 or possibly 2 layers. In this case if your "Concept" assemblies also contain other extra logic (such as WinForms) you are just referencing extra code that will never be used. For this reason its also normal to separate out into conceptual layers if you have them, for example:

Company.Project.Concept.Processing.dll
Company.Project.Concept.WinForms.dll

I.e. in the example you gave I'm advocating that if anything you would want 9 assemblies, not 3:

MyProject.ConceptA.Domain.dll
MyProject.ConceptA.Presentation.dll
MyProject.ConceptA.WinForms.dll

Of course splitting your project down into hundereds of assemblies is completely pointless unless these individual concepts are actually going to be used elsewhere which brings me back to my first point - don't bother splitting up assemblies unless you actually need to, or to put it another way split your assemblies up into the re-usable components that make sense:

  • If nobody else is going to use your Windows Forms controls then don't bother to split them into a separate assembly
  • If most people are going to use ConceptB and ConceptA together then combine them into a single assembly
  • If most people are going to want to use the Domain and Presentation layers together, combine them into a single assembly

As a working example I automatically opt to split smaller projects into two assemblies - the application itself which contains all the "presentation" (be it Web, WinForms, WPF or a Console app), and another assembly which contains the "meat" of the application - the underlying functionality being exposed by your application (e.g. image processing, data retrieval etc...). This helps if I ever want to expose the same functionality in a different style of application.

Once more though I would err on the side of too few assemblies rather than too many - its easier to split an assembly in two than it is to combine two assemblies back into one. Unless you can find a compelling reason to split an assembly / project up into multiple assemblies, don't bother.

like image 159
Justin Avatar answered Oct 12 '22 11:10

Justin