tags:

views:

568

answers:

5

Say you are writing an app like Photoshop where you have effects (filters), etc, should one make each of these filters a separate assembly using a separate project?

The main idea is to have each of these filters as nodes, so think of it like:

sourceImage -> Sharpen -> Darken -> Contrast -> Blur ...

It seems to me that it would make sense to have dll files like:

[Filters folder]   
Sharpen.dll  
Darken.dll
Contrast.dll
Blur.dll

But it would be hard to manage them like that, and that would prevent me to use the internal keyword for class members, right?

So right now I only have 1 dll for all filters.

What's the best practices for organizing assemblies?

+5  A: 

I wouldn't restrict yourself to one filter per assembly. You may well want to group assemblies which implement similar functionality - e.g. colour/contrast together, while keeping them separate from very different kinds of filters (e.g. edge enhancing).

Just one bit of anecdotal evidence: I've often seen applications be difficult to manage due to having too many assemblies. I can't remember ever seeing one which had problems because it hadn't split the assemblies up enough. I'm not saying it can't happen - just that I haven't seen it.

Jon Skeet
+1 Anecdotal evidence == experience ~= best practice
Andrew Hare
Thanks Jon. I see your point. Just one more thing I wonder, if I had say 10 assemblies for the whole app as separate projects in the same solution file, would I be able to use internal between different assemblies? I remember not, but then I am having a hard time breaking up the base functionality
Joan Venge
from the app itself. So at the end I end up say, PhotoshopLib.dll and Photoshop.exe.
Joan Venge
You can use internal between different assemblies if you make them a friend assemblies. Look at the InternalsVisibleToAttribute.
Petar Repac
Or is using internal not a very good practice in the first place that should be replaced by a better practice.
Joan Venge
Thanks Petar, I didn't know that.
Joan Venge
BTW, it's not what I would suggest. It is a possibility though.
Petar Repac
I've only ever used InternalsVisibleTo so that unit tests can get at internal methods. But by and large internal is a good idea IMO.
Jon Skeet
Downvoters: please comment, or your downvote is pretty pointless.
Jon Skeet
I've seen major problems in our code base because assemblies weren't split enough. We had a common Core assembly where everyone put their core stuff - apparently because they thought adding new assemblies was a bad thing. In the long run, coupling between all the discrete services in the core library crept in because nothing prevents programmers from doing it. It was a nightmare to fix.It would not have been a problem if there's a way to detect invalid coupling between namespaces in the same assembly (i.e. namespaceA is not allowed to know about namespaceB). Is there a tool for that?
Anthony Brien
+2  A: 

I think a better way may be to have a Filters assembly with Sharpen, Darken, Contrast, and Blur namespaces for the types in that assembly. It really all depends on how modular you need each bit of functionality to be.

Andrew Hare
Thanks Andrew good idea.
Joan Venge
A: 

Having separate assemblies makes it much easier to add more without recompilation. In particular, if you use some type of DI solution (like MEF), you can load these assemblies at runtime and inject them into your program.

However, this will require that your main program exposes an appropriate, public interface, so the other assemblies can work with your types. Internal modifiers become trickier, since you'd have to set the internals visible attribute for each assembly you want to have access to your internals.

Reed Copsey
+5  A: 

Patrick Smacchia author of NDepend tool suggest that the number of assemblies is kept low. Look here. This also implies to a certain level that you use NDepend to manage dependencies between namespaces. Also, compilation is faster if you have less assemblies and deployment is easier.

I would second Reed Copsey that DI (like StructureMap) solution could provide you with extensibility and testability if that's what you are after.

Petar Repac
+2  A: 

Reasons to have separate assemblies:

  • You can deploy them individually and load them at runtime using reflection (i.e., plugins). But make sure this level of added complexity is worth it.
  • You can separate your business logic from your UI and theoretically (occasionally in practice) have a separate UI.
  • You have an library of utility classes that you might want to use in both a Windows Forms and a ASP.NET application.
  • You can put your business logic in a DLL and then have a DLL of unit tests to exercise that code.
  • Along with the last point, you can configure some assemblies to only build in Debug or Release mode. So you might build your unit test assembly only in Debug mode and not ship it in Release mode. Or you might have an additional helper program (maybe for installation) that only builds for Release.

Reasons to avoid separate assemblies:

  • It adds complexity. Don't organize your code into multiple assemblies just based on a theoretical "modeling" of your program. Make sure the additional complexity actually buys you some greater value.
  • It slows down compiles/builds.
  • You can't have circular references between assemblies, so you have to jump through a lot of hoops and "plumbing abstractions" if you discover that your assembly needs to access classes and methods from a higher-level assembly. For instance, if your Windows Forms UI (.exe) assembly calls into a business logic DLL, the DLL can't reference the UI classes without a lot of messing around with interfaces and passing references across the layers.

I think this is something that comes with experience. My own experience has been that as I've matured as a .NET developer, I've become less inclined to create more assemblies unless there's a very compelling reason.

Jesse Smith