tags:

views:

77

answers:

4

Suppose I'm making a new library, Jokes, with a small API. In the interest of making my API easy to use I put it in the base namespace:

namespace Jokes

    --> public interface IJoker
        --> string Joke();

    --> public static class Jokers
        --> public static IJoker NewSlapstickJoker()
        --> public static IJoker NewAbsurdJoker()
        --> public static IJoker NewCheesyJoker()

The implementations of the Jokers are internal:

--> internal class SlapstickJoker : IJoker
--> internal class AbsurdJoker : IJoker
--> internal class CheesyJoker : IJoker

Now I'm pretty sure the following is a guideline to follow (could someone please verify?):

  • Do not access types from subnamespaces from the root namespace. (For example, the types in System are ignorant of types in System.Drawing).

Does this guideline apply to internal classes? To avoid polluting my root namespace, I would like to put my internal classes in Jokes.Internal. This would mean that a type in the Jokes namespace (Jokers) would know about types in the subnamespace Jokes.Internal. Is this ok?

+1  A: 

Namespaces serve several key purposes:

  1. They help avoid naming collisions between types that different developers and different organizations create and share.
  2. They help to organize types into groups to make it easier to understand what they do and which types relate to one another or are used together.

Now to your specific question. Referring to types in an inner namespace from the outer one isn't highly desirable - but it's not horrible either. While I can't think of one now, I wouldn't be surprised if there are cases in the .NET framework itself where this situation exists. As a general design principle, it a good idea to build code in layers; and often those layers are structured such that less "specialized" code is unaware of more "specific code".

Namespace nesting is one way of separating more specialized types from less specialized ones. So the namespace System contains very general and broadly applicable types - while System.Drawing is more specialized and contains types relating to image and visual manipulation.

What you should avoid doing, however, is using namespaces to group types based on accessibility. This is definitely an abuse of namespaces - and is likely to cause problems over the long run (particularly since it's common to widen the accessibility of a type - but it can be quite difficult to change what namespace it's part of).

In my opinion, however, as long as you are consistent in what your doing, and there's a sensible of division of types between namespaces, I think you'll be alright.

LBushkin
A: 

It is not a big deal if you do what you propose, but I think it would be better to avoid the "Jokes.Internal" namespace. I would not think of the internal classes as "polluting" your root namespace.

Whatever the case, I think it is definately unorthodox to make namespaces that match your visibility declarations.

Brent Arias
+1  A: 

To avoid polluting your root namespace I suggest either of:

  • Declare the classes internal instead of public (so that they're not visible to users of your API, outside the assembly)

  • Declare then as nested inner classes of Jokers (so that they're not visible outside the Jokers class)

ChrisW
I would recommend to make them nested inside `Jokers`, too, if you can.
Timwi
+2  A: 

To avoid polluting my root namespace, I would like to put my internal classes in Jokes.Internal. This would mean that a type in the Jokes namespace (Jokers) would know about types in the subnamespace Jokes.Internal. Is this ok?

Yes, that's fine. The main guidance about not having types in a namespace rely on types within a "sub" namespace really is more about the public API. The internal classes, and namespaces used only by internal types, is really an implementation detail, and outside of any guidance of the sort.

I would stick to something consistent that you find makes sense. Using an Internal namespace seems reasonable (though I'd potentially do something like namespace Jokes.Implementations).

Also, given that your Jokers class is constructing new instances, it's basically a factory. You might want to consider naming something more like JokerFactory to make this obvious. Jokers, to me, would suggest that there would be a collection of Joker instances contained within the class, not a set of factory methods.

Reed Copsey
+1 JokerFactory
ChrisW