Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,125 | Comments: 45,492

filter by tags archive

Public vs. Published

time to read 2 min | 306 words

imageOne of the thing that you see some people agonizing about is what they should be exposed to the outside world. On the one hand, people have heard all about encapsulation, and how it is going to save the world. On the other hand, we want to expose functionality to the outside world, be it for testing or for advance usages of your software.

Something that I wish that C# had is the published alias to the public keyword, that would have expressed intent in a much easier fashion than just public.

That said, I found a very useful approach to handling this myself. Separating interface and implementation. Let us look at an example:

public interface ICommand
     void Init(string[] args);
     void Execute();

And an implementation of that:

public class MyCommand : ICommand
       public string Key { get; set; }
       public long ByteCount { get; set; }

       public void Init(string [] args)
		// parse args to key & byte count

Now, if I want to test that I am getting the right thing, I can, easily. At the same time, the published interface of this is ICommand, not whatever is public in MyCommand.

In situations where I have one to one mapping between interfaces and implementations (IUserRepository and UserRepository), this is even more pronounced.


Andrey Shchekin

I think it's exactly what 'internal' is for.

I always make things like UserRepository internal.


I use this all the time for my repository and service classes. It allows me to use property injection without publishing the public properties. I can still access those properties if I want to, but they aren't a part of the "published" interface to those classes.


congrats, you've discovered OOP! ;)

Adam Vandenberg

I've used the "Interface as published" thing before on my projects. I had class with a HUGE set of public methods being passed around, and I finally went around partitioning them into separate iterfaces, and rewriting the client code to accept only the narrowed interface.

This worked wonders.

I was able to componentize the kitchen-sink class and finally refactor the responsibilities into wherever they needed to go, rather than in the kitchen-sink.

It helps intellisense within the client code too, as I only see those methods which I "ought" be using, instead of everything the class has.

Ayende Rahien


Internal is a bad solution, it means that you are only exposing things to the current assembly.

Testing, advance scenarios needs that access as well

Petar Repac


you can test internal members if you make test assembly a friend assembly (with InternalsVisibleToAttribute)

Ayende Rahien

Petar, I am aware of that.

I strongly dislike this method


Adding InternalsVisibleTo a project's AssemblyInfo.cs will allow other explicitly defined assemblies access to internal members. This is really helpful for unit testing.


[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("UnitTests, PublicKeyToken=123456789abcdef0")]



Why wouldn't you mark the set parts of the properties to private since the way they should be initialized is via the Init method?

Andrey Shchekin

Testing works extremely well with InternalsVisibleTo. Also it seems the right thing to do -- why do something as big as making everything public just for testing purposes?

I always try to write my code to be test ignorant (making code modular or using interfaces are common sense good design decisions, not test-forced ones). Doing something 'just for tests' feels as bad as doing something 'just for persistence' or 'just for specific IoC container'.

But if you have an advanced scenario when you need these classes to be public, probably it means they are 'published' as well.

Ayende Rahien

You seem to be ignoring the part of testing not the only thing required.

And published is not the same as public. For published, I want to support this.

For public, it means that you can do things with it, but it is your responsability

Petar Repac


I really don't see how "other explicitly defined assemblies" could access internal members. It would defeat the whole purpose of friend assemblies.


could you say why you dislike this method ? Because I see it very much like Andrey.

The other way to test internal stuff could be to implement test classes inside the tested assembly itself and manage builds so that test classes are not included in release version. With partial classes maybe we could test private stuff to. Haven't tried this scenario myself..

Ayende Rahien

Because testability is a secondary concern. I often need to be able to support additional functionality, and I found out that creating this distinction means that I can get pretty good results over a long period of time.

here is an example:


Andrey Shchekin

I do not see any be-public requirements here: http://www.ayende.com/Blog/archive/2008/01/24/Interception-as-an-extensibility-mechanism.aspx, what am I missing?

Andrey Shchekin

I do not see any be-public requirements here: http://www.ayende.com/Blog/archive/2008/01/24/Interception-as-an-extensibility-mechanism.aspx, what am I missing?

Jon Skeet

Out of interest, has anyone here ever seen a good use for InternalsVisibleTo other than testing? That's the only use I've had for it so far, and I'd be slightly worried at other uses, I suspect. If anyone's found one, I'd be interested to hear about it.

Paul Batum

Jon, when working with NHibernate, I use InternalsVisibleTo to give Castle.DynamicProxy access to the internals of my domain model.This allows me to use the lazy loading that Castle.DynamicProxy provides while keeping stricter controls on the visibility of constructors.

George Spofford

The first textbook I ever came across on computer security discussed role-based security access to functions prior to applying it to things like file and object access. I agree that public/private/protected/internal are too gross in their scopes- very convenient for lots of cases, but not adequate. I for one would like to be able to unit-test "private" methods and classes as well. Of course, role-based or named-entity-based access authorization for code introduces a set of questions, but I'm quite confident that a broader set of cases could be handled with the answers that are easier to arrive at.

Colin Jack

Noticed you have Execute on the interface but not on the class...


"Doing something 'just for tests' feels as bad as doing something 'just for persistence' or 'just for specific IoC container'."

I think a lot of the time this is true, changes put in for testing don't necessarily prove that useful. That is not an argument against TDDD though, just not sure always designing for testability is always a good approach.

@Jon Skeet

Good, maybe not but I've seen it used where you have a seperation between layers but actually there is a tight relationship. For example only an AccountService (in one project) should access a member on Account (in another project), in those cases you can make the member public and only use it from AccountService or just use InternalsVisibleTo in order to give the project containing AccountService access.

Comment preview

Comments have been closed on this topic.


  1. RavenDB 3.5 Whirlwind tour: I need to be free to explore my data - 13 hours from now
  2. RavenDB 3.5 whirl wind tour: I'll have the 3+1 goodies to go, please - 4 days from now
  3. The design of RavenDB 4.0: Voron has a one track mind - 5 days from now
  4. RavenDB 3.5 whirl wind tour: Digging deep into the internals - 6 days from now
  5. The design of RavenDB 4.0: Separation of indexes and documents - 7 days from now

And 11 more posts are pending...

There are posts all the way to May 30, 2016


  1. The design of RavenDB 4.0 (14):
    05 May 2016 - Physically segregating collections
  2. RavenDB 3.5 whirl wind tour (14):
    04 May 2016 - I’ll find who is taking my I/O bandwidth and they SHALL pay
  3. Tasks for the new comer (2):
    15 Apr 2016 - Quartz.NET with RavenDB
  4. Code through the looking glass (5):
    18 Mar 2016 - And a linear search to rule them
  5. Find the bug (8):
    29 Feb 2016 - When you can't rely on your own identity
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats