What number of classes do you think is ideal per one namespace "branch"? At which point would one decide to break one namespace into multiple ones? Let's not discuss the logical grouping of classes (assume they are logically grouped properly), I am, at this point, focused on the maintainable vs. not maintainable number of classes.
With modern IDEs and other dev tools, I would say that if all the classes belong in a namespace, then there is no arbitrary number at which you should break up a namespace just for maintainability.
I know you don't want to discuss logical grouping, however to do a split you need to be able to group the two different namespaces. I'd start considering a new namespace at around 30 classes; however I wouldn't consider it a major concern.
I think a namespace should be as large as it needs to be. If there is a logical reason to create a sibling namespace or child namespace, then do so. The main reason as I see it to split into namespaces is to ease development, making it easier for developers to navigate the namespace hierarchy to find what they need.
If you have one namespace with lots of types, and you feel it's difficult to find certain ones, then consider moving them to another namespace. I would use a child namespace if the types are specializing the parent namespace types, and a sibling namespace if the types can be used without the original namespace types or have a different purpose. Of course, it all depends on what you're creating and the target audience.
If a namespace has less than 20 types, it's unlikely to be worth splitting. However, you should consider namespace allocation during design so that you know up front when developing, what types go in which namespaces. If you do namespace allocation during development, expect a lot of refactoring as you determine what should go where.
"42? No, it doesn't work..."
Ok, let's put our programming prowess to work and see what is Microsoft's opinion:
# IronPython
import System
exported_types = [
(t.Namespace, t.Name)
for t in System.Int32().GetType().Assembly.GetExportedTypes()]
import itertools
get_ns = lambda (ns, typename): ns
sorted_exported_types = sorted(exported_types, key=get_ns)
counts_per_ns = dict(
(ns, len(list(typenames)))
for ns, typenames
in itertools.groupby(sorted_exported_types, get_ns))
counts = sorted(counts_per_ns.values())
print 'Min:', counts[0]
print 'Max:', counts[-1]
print 'Avg:', sum(counts) / len(counts)
print 'Med:',
if len(counts) % 2:
print counts[len(counts) / 2]
else: # ignoring len == 1 case
print (counts[len(counts) / 2 - 1] + counts[len(counts) / 2]) / 2
And this gives us the following statistics on number of types per namespace:
C:\tools\nspop>ipy nspop.py
Min: 1
Max: 173
Avg: 27
Med: 15
I must say I find all of the above very surprising reading.
Usability experts tell us to keep the number of choices in a menu to a limited number so we can immediately see all the choices. The same applies to how you organise your work.
I would typically expect 4-10 types in a namespace. Saves so much hunting round for stuff and scrolling up and down. It's so quick and easy to move stuff around using resharper that I don't see any reason why not to.
Another thing that should mentioned is that it often pays to put a class containing extension methods in its own namespace, so that you can enable or disable those extension methods with a using
directive. So if the thing in the namespace is a static class containing extension methods, the answer is 1.
One thing that isn't covered here, though it relates to Chris' point in a way, is that the learnabilty of a namespace isn't just related to the number of items.
(Incidentally, this applies to "namespace" in the widest sense - a class itself is a namespace in the general sense in that it contains certain names that mean a different thing in that context than they might in another, an enum is a namespace in this sense too).
Let's say I encounter an XML-related namespace with an Element class. I learn a bit about this and when I look at the Attribute class, I see some similarity. When I then see a ProcessingInstruction class, I can make a reasonable guess about how it works (and it's probably a design flaw if I guess completely wrong, at best differences need not just to be documented, but explained). I can guess that there's a Comment class before I even see it. I'll go looking for your TextNode class and wonder if these all inherit from Node rather than having to learn about them from the docs. I'll wonder which of several reasonable approaches you took with your Lang class rather than wonder if it's there.
Because it all relates to a domain I already have knowledge of, the conceptual "cost" of these seven classes is much, much less than if the seven classes where called, Sheep, Television, FallOfSaigon, Enuii, AmandaPalmersSoloWork, ForArtsSakeQuotient and DueProcess.
This relates to Chirs' point, because he says that we are advised for the sake of usability to keep the number of choices down. However, if we have a choice of countries in alphabetical order, we immediately grok the whole list and pick the one we need instantly, so the advice to keep choices down doesn't apply (indeed, a few options at a time can be both less useful and potentially insulting).
If your namespace has 200 names, but you only have to really learn half a dozen to understand the lot, then it'll be much easier to grok than having a dozen names with little relation to each other.