C# Code Organization – Good Ways to Share Internal Helpers

ccode-organizationnet

All my projects share the same base library that I have build up over quite some time. It contains utilities and static helper classes to assist them where .NET doesn't exactly offer what I want. Originally all the helpers were written mainly to serve an internal purpose and it has to stay that way, but sometimes they prove very useful to other assemblies. Now making them public in a reliable way is more complicated than most would think, for example all methods that assume nullable types must now contain argument checking while not charging internal utilities with the price of doing so. The price might be negligible, but it is far from right.

While refactoring, I have revised this case multiple times and I've come up with the following solutions so far:

  1. Have an internal and public class for each helper
    The internal class contains the actual code while the public class serves as an access point which does argument checking.
    Cons:

    • The internal class requires a prefix to avoid ambiguity (the best presentation should be reserved for public types)
    • It isn't possible to discriminate methods that don't need argument checking
       
  2. Have one class that contains both internal and public members (as conventionally implemented in .NET framework).
    At first, this might sound like the best possible solution, but it has the same first unpleasant con as solution 1.
    Cons:

    • Internal methods require a prefix to avoid ambiguity
       
  3. Have an internal class which is implemented by the public class that overrides any members that require argument checking.
    Cons:

    • Is non-static, atleast one instantiation is required. This doesn't really fit into the helper class idea, since it generally consists of independent fragments of code, it should not require instantiation.
    • Non-static methods are also slower by a negligible degree, which doesn't really justify this option either.

There is one general and unavoidable consequence, alot of maintenance is necessary because every internal member will require a public counterpart.

A note on solution 1:
The first consequence can be avoided by putting both classes in different namespaces, for example you can have the real helper in the root namespace and the public helper in a namespace called "Helpers".

Best Answer

No, this doesn't answer your question directly, but mostly because I believe your problem is rooted elsewhere.

Personally I tend to stay away from "helper classes" and libraries. Such code tends to be a dumping ground for code that doesn't have a home, and leads to poor design. From what I've gathered your suggesting to have an assembly attached to each of your 'real' projects so that it can share some common code. And what I see happening is a bunch of code that gets loaded into the app domain, and maybe 10% of it actually used by any given segment of your domain. Which may end up costing you more than a few checks on public members.

I would suggest analyzing what parts of your domain will actually need specific code shared, and design the reusable code around that. Personally I prefer the usage of extension methods; You can tie specific reusable code to a specific type (avoid extending string, int or the like) giving it a nice comfortable home, and easy to understand code.

When all else fails remember: "Performance is not a problem until it is a problem. Your time is more valuable than a few CPU cycles"