Overview
We will accomplish building reusability into our project by exposing the interfaces to our objects publicly while hiding the implementation in an assembly containing only internal classes and then exposing the interfaces to our classes in a "builder" assembly. The builder assembly will be the only assembly allowed to make instances of the core objects so the instantiation of our objects are effectively hidden and not available outside the builder classes.
Project Core
For this project we will build a simple Money object that can be added. Our four assemblies will consist of
- FriendlyTesting.Core: Contains our interface definitions.
- FriendlyTesting.Hidden: Contains our implementation in classes internal to this assembly.
- FriendlyTesting.Friend: Exposes instantiation of the internal classes in FriendlyTesting.Hidden.
- FriendlyTesting.TestHarness: The final test harness console project.

Interfaces
Our interfaces define an IMoney interface that is IAddable<IMoney> (so we can add up our money in the test harness).

Concrete Implementation
The internal Money class implements IMoney and is "hidden" because it can only be instantiated from inside the containing assembly or a friend assembly.

Builders
The builder class will implement an interface specific to the builder: IMoneyMaker. The builder's responsibility is to instantiate the Money object and expose it through the IMoney interface.

Our solution
The first thing to note is that the Money is hidden in it's assembly because it is marked as internal.
internal class Money: IMoney, IAddable<IMoney>
As a result, from our money builder class, the money is not available because the Money class is only internally available to the FriendlyTesting.Hidden assembly. As a result, we can not instantiate a Money object until we make the FriendlyTesting.Friend assembly a "friend" of the FriendlyTesting.Hidden assembly indicating that it can be trusted with the internal classes.
public class MoneyBuilder: IMoneyMaker
{
#region IMoneyMaker Members
public IMoney MakeMoney(double amount)
{
// Money is not available here...
// it is internal to FriendlyTesting.Hidden
}
#endregion
}
Creating a Friendly Assembly
Our goal is to make instantiation possible only through our builder class, so in the next few steps we'll make these two assemblies play nicely with each other.
Step 1) Strongly Naming the Assemblies
The first step is to make all the assemblies strong named. So we will create keys for our two assemblies (friend and hidden) through the "sn" visual studio command line utility (Start>Programs>Visual Studio>Visual Studio Tools>Visual Studio Command Prompt).
Command line syntax:
sn -k <new key name>
Actual command:
sn -k FriendlyKey.snk
Generating the key for the FriendlyTesting.Friend assembly:

Generating the key for the FriendlyTesting.Hidden assembly:

Because these two assemblies are strongly named, all referenced assemblies also have to be strongly named, so we'll do the same thing for the FriendlyTesing.Core assembly that holds our core interface definitions.
Step 2) Add the Keys to the Projects
Now we have to add the keys we generated to their respective projects through the project's properties (right click on the project and select 'Properties'). We'll walk through this for the FriendlyTesting.Friend assembly:

Click "Sign the assembly" and select browse from the drop down that is activated.
Open FriendKey.snk and it will now appear in our project

Add HiddenKey.snk to the friendlyTesting.Hidden project and the core key to the core project in the same way.

Step 3) Extract public key for friend assembly
Next we will extract the public key from our FriendlyKey.snk (the key for the FriendlyTesting.Friend project). We need information from the public key in order to let the hidden project know which assemblies to be friendly with. We will generate a new public key called "FriendlyKey_public.snk" with the following command:
Command line syntax:
sn -p <existing private key name> <new public key to be created>
Actual command:
sn -p FriendlyKey.snk FriendlyKey_public.snk

Step 4) find out the public key's info
Next we will show the public key's info with the following command
Command line syntax:
sn -tp <public key name>
Actual command:
sn -tp FriendlyKey_public.snk

Step 5) Name a friend in the hidden assembly.
Next, we will update the Assembly.cs file in the FriendlyTesting.Hidden project making our hidden assembly's internal member available to the new friend.
Add the following line which contains the public key information we just gathered to the FriendlyTesting.Hidden Assembly.cs file. Assembly.cs is located in the project's Properties folder:
[assembly: InternalsVisibleTo("FriendlyTesting.Friend, PublicKey=00240000048000009400000006020000002400005253413100040000010
001000bfc58cfde00927bad3d28eb63098979418a31af879120f08c8babb49c998a0a2a
f6416679763add28c735f3e8503301336339c321cfd23b6a346df22b32bf83e01c2aac16
f5e64c355c1c66ecc892c6e8986a2c1fc05fcc5f90f595decf968506b41c64d49cfe5431d
eeed3d179c09c871eac6b10fcad24f473bcd3731a1fb2")]
After this we find that FriendlyMoney.Friend has access to the internal members of the FriendlyTesting.Hidden project. So we can make money with our MoneyBuilder.
public class MoneyBuilder: IMoneyMaker
{
#region IMoneyMaker Members
public IMoney MakeMoney(double amount)
{
return FriendlyTesting.Hidden.Money.Instantiate(amount);
}
#endregion
}
Wrap up: Test Harness
In any other projects in which we would like to use our Money class, we can only instantiate it through the MoneyBuilder and our Money object can now only be referenced through the IMoney or IAddable<> interfaces.
class Program
{
static void
{
IMoneyMaker builder = MoneyBuilder.Instantiate();
// NOTE: FriendlyTesting.Hidden has no members available here
// so we are required to get IMoney through the MoneyBuilder
IMoney bagODoughA = builder.MakeMoney(10.25);
IMoney bagODoughB = builder.MakeMoney(5.50);
IMoney allDough = bagODoughA.Add(bagODoughB);
Console.WriteLine("Total Moolah: " +
allDough.Amount.ToString());
Console.ReadLine();
}
}
This approach gives us a great deal of flexibility because we control how our class will be consumed by other projects and we can ensure nothing will break by changing backend implementation... as long as the code works and the IMoney and IAddable<> interfaces do not change.
If you download the project, you can verify that the Money object is not available to the FriendlyTesting.TestHarness assembly. Also, if you remove the line added to FriendlyTesting.Hidden Assembly.cs, the project will not compile because the Money object will no longer be visible to the FriendlyTesting.Friendly assembly.
I hope you found this article useful.
Until next time,
Happy coding
Matthew CochraneditedPosted Nov 6, 2006, 5:29 PMEdited Nov 7, 2006, 9:40 AM
>Making a change, any change, to an interface is considered a breaking >change. If for any reason one of your customers implemented one of >your interfaces, then any code that relied on the interface would be >broken.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p> >This is why there are so many numbered COM interfaces. Each time they >wanted to add functionality to the class, they had to create a new >interface.<o:p></o:p> OK – I got it. I definitely see your point. Thanks for the clarification. I think we need to make the distinction of an Interface in terms of a language element and the more abstract idea of an interface which is the "hooks" exposed by our classes. The language element Interface (capitol I) is a predefined "hook". So are abstract classes. We will have breaks not only if the Interface (capitol I) change, but also any of the abstract classes. Essentially, adding a new abstract method to a abstract class is the same thing as adding a method to an Interface (capitol I). I did not mean to give the impression that an Interface (capitol) is the only means of exposing "hooks" to clients and am in 100% agreement that we could expose abstract classes that act as "interfaces" to our core implementation. Interfaces and abstract classes are very similar in that they both expose some hooks, the difference being the abstract class has some implementation embedded and the interface does not. Publishing either the interface, abstract class, or both together would have to be considered on a case-by-case basis. Personally, I need a pretty compelling argument to inherit from a base class because we get one (and only one) object we can inherit from, while we can implement as many Interfaces (capitol I) as we want. <o:p></o:p> If only the Interfaces (capitol I) are exposed, they should be designed granularly enough to provide for each facet of functionality/data that the implementing object provides. Kind of like "ICloneable()" and "IXmlSerializable()". If the interface (lower case i) to the object needed to change, we could add a new Interface (capitol I) that exposes the new functionality/data. I would hope the initial Interfaces (capitol I) would be well thought out enough so that the defined "hooks" would not change and the object could implement a new Interface (capitol I) to expose any new functionality the class is to implement. If we did need to add to an Interface (capitol I), we could also ensure any new interfaces implement legacy interfaces to extend functionality and not “break” client code any more than adding a new abstract method to a base class would.<o:p></o:p> INewInterfaceA:IOldInterfaceB { }<o:p></o:p> If we have an Interface (capitol I) that exposes all the functionality an object has to offer, it is pretty much pointless and would need to be refactored into more granular functional definitions. Having a large (non-granular) Interface (capitol I) is definitely a very bad idea for exactly for the reasons you stated and I think the interface design is a crucial part of the process. If the interfaces are not well thought out it would be a big mess. Interface definition does help us keep object loosely coupled and just expose the elements necessary for interaction. If we expose a whole base class, there is no guarantee that the exposed methods/properties would be used appropriately. If we pass an interface, we can control how object interact. >> Also, I would not want anyone else making versions of our product. I would >> prefer to keep all development of our software in-house and distribute >> controlled updates to the interface libraries and core functionality when >> necessary. >You are doing the exact opposite of what your stated goal is. By >releasing interface libraries that anyone can implement, you have made >it easier for competitors to create drop-in replacements. All they >have to do is implement your interfaces. They can even do it by >degrees, using your own classes to test against.<o:p></o:p> >If you exposed actual classes, they would have to try to mirror it >all. Most companies wouldn't bother, and would instead require >customers to account for the differences between implementations. This >makes their barrier of entry higher, allowing you to retain more >customers.<o:p></o:p> Unfortunately, despite how good any obfuscation tool we have is, C#/IL code can be easily reverse engineered if someone has the right tools which are readily available. Immoral? You bet. Illegal? You bet. Will that stop people from doing it anyways? I doubt it. In fact, even if we have a component written in C++ and wrapped w/ C#, there are some really smart people out there who can still figure it out. The best place for companies to protect their intellectual property is in the courts. Keep in mind, authors generally try to keep sample code as simple as possible. It is a mistake to think that it would by any means be a fully functional framework on which to build. At a point this becomes a religious debate which some people are very emotionally attached to one side or the other but I truly appreciate your comments and appreciate the opportunity for this dialogue and feel some very valid points were made.<o:p></o:p> Thanks, -Matt
Matthew CochraneditedPosted Nov 6, 2006, 4:26 PMEdited Nov 6, 2006, 4:32 PM
> How so? Adding new properties/methods to existing interfaces should not > break existing code (unless I'm missing something). The only changes that > will break client code would be to the existing signatures that clients have > already coded against or changes to the expected functionality of an already > existing method. Making a change, any change, to an interface is considered a breaking change. If for any reason one of your customers implemented one of your interfaces, then any code that relied on the interface would be broken. This is why there are so many numbered COM interfaces. Each time they wanted to add functionality to the class, they had to create a new interface. > Also, I would not want anyone else making versions of our product. I would > prefer to keep all development of our software in-house and distribute > controlled updates to the interface libraries and core functionality when > necessary. "Try FooBar 2000. It supports all of the IMax interfaces, is half the price, and can cut through a tin can without dulling." You are doing the exact opposite of what your stated goal is. By releasing interface libraries that anyone can implement, you have made it easier for competitors to create drop-in replacements. All they have to do is implement your interfaces. They can even do it by degrees, using your own classes to test against. If you exposed actual classes, they would have to try to mirror it all. Most companies wouldn't bother, and would instead require customers to account for the differences between implementations. This makes their barrier of entry higher, allowing you to retain more customers. > It is true that they can not inherit from the core classes but this is precisely the point of this approach. Then why not simply mark them as sealed/NotInheritable? You get the same effect without losing out on other benefits like... 1. The ability to add new methods with making a breaking change. 2. You don't expose an interface that others can implement. 3. You allow direct object creation with the new keyword. (There are programmers who will not use a library if the only way to create objects is via a factory.) 4. You can support operator overloading when applicable. (Though this is rare.) > Again, this project is not an attempt to build an extensible class library. > Our primary goal is to [1] provide some core functionality, [2] separate the > interfaces from the implementation and [3] publish the interfaces for > consumption. Therefore, anything that is needed for a client to code > against should be provided in the interface. Goal 1 is achived either way, so we can skip it for now. Goal 2 is also achieved either way. Keep in mind that the public members of the class also are an interface. This interface, known as the "public interface" or "default interface" in some text books, is just as good as an explicit interface at seperating the interface from the implementation. This goal is achieved by not blindly makring everything in the class public. It is failed by marking too much public, which can occur with or without explicit interfaces. The logic behind that goal goes back to the days of structs, where in you couldn't mark anything as private. In systems like C, all of your implementation detail is exposed for anyone to tamper with. Goal 3 is also achieved either way. As I stated before, the classes public interface is quite suitable for creating a consumable interface. One goal you met, but did not state, is "publish the interfaces for implementation". > A good example of this is the ADO.NET interfaces. If we code everything > against a SqlServer or Oracle implementations of the core data interfaces we > will have to opportunity to override some base methods but the tradeoff in > doing so is that we will have brittle software because we can not change the > backend database without having to re-write the software. Alternatively, if > we know that there is a possibility of a future database change, we can code > directly against the provided interfaces and have a higher level of > flexibility. Look at that API code again and compare it to your recommendation, for it does illustrate some good design. 1. They provide choice for the consumer (people using the API). They can choose to program against the interfaces, or they can use the richer functionality of the concrete classes. You only offer one option. 2. They provide a set of extension points for implementors (people extending the API) via interfaces. You offer this, though you stated you don't intend people to implement your interfaces. 3. They provide more then one implementation for each interface. From what I can tell, you are only offering one. > Also, if you think about it Microsoft and the development community as a > whole are moving towards a service oriented architecture (SOA) approach > which is in essence the separation of implementation and interface. I think that is off topic to the discussion. Windows Communication Foundation uses explicit interfaces to seperate the implementation because the implementation runs on a seperate machine. There is no local implementation to use other than the auto-generated code behind the stub. > We are > just doing the same thing by providing functionality through an interface > and "hiding" the implementation, just a WSDL gives us an interface to > interact with web services. I think we would be hard pressed finding > someone who advocates doing away with this architectural approach (or maybe > not). The thing is you are not actually hiding anything that you were not hiding before. I'll leave you with these quotes from "Framework Design Guidelines" http://www.awprofessional.com/articles/article.asp?p=423349&seqNum=3&rl=1 "One of the most common arguments in favor of interfaces is that they allow separating contract from the implementation. However, the argument incorrectly assumes that you cannot separate contracts from implementation using classes. Abstract classes residing in a separate ssembly from their concrete implementations are a great way toa achieve such separation." "Over the course of the three versions of the .NET Framework, I have talked about this guideline with quite a few developers on our team. Many of them, including those who initially disagreed with the guideline, have said that they regret having shipped some API as an interface. I have not heard of even one case in which somebody regretted that they shipped a class." Jonathan Allen
Matthew CochraneditedPosted Nov 6, 2006, 2:30 PMEdited Nov 6, 2006, 3:07 PM
What we are doing here is providing a separation of interface from implementation. Ideally, a client only needs to know about the interface and so any implementation can be replaced without the need to change the client code. With interfaced based development our goal is to have the core unit of reuse be the interface and not the class. A great book on this subject "Programming .NET Components" by Lowy. Check it out, it's defiantly worth reading and goes into depth on the subject. To each of your points: Point 1: "Your solution doesn't support versioning. You cannot add new properties or methods without making a breaking change to the interface." How so? Adding new properties/methods to existing interfaces should not break existing code (unless I'm missing something). The only changes that will break client code would be to the existing signatures that clients have already coded against or changes to the expected functionality of an already existing method. Also, I would not want anyone else making versions of our product. I would prefer to keep all development of our software in-house and distribute controlled updates to the interface libraries and core functionality when necessary. It may be I'm not understanding your comment. Where do you see the breaks occurring? Point 2: "Your solution isn't easily extensible. By using interfaces for everything, users cannot inherit from your implementations. They have to either reimplement everything from scratch or write wrapper classes." It is true that they can not inherit from the core classes but this is precisely the point of this approach. A couple of things to keep in mind: 1) The code is easily extensible for people who have access to the source code (which we may not necessarily want to distribute and have just anybody extend). 2) Inheritance is not the only option for implementation of the functionality in another class. Composition is also a viable alternative. If a library does not provide the exact functionality needed I don't see a huge problem with using a few decorators (wrappers) with the caveat that if everything has to be decorated you are probably using the wrong core library. 3) We will be providing implementation with any interfaces we distribute and the whole purpose for a client to use our library would be for the underlying functionality provided. I think it is safe to assume that a clients primary interests are not in the interfaces exposed nor the approach that has been used to implement the functionality. I don't see why a client would want to re-write what we are already providing. If that were the case, the provided functionality would be useless and the client would develop what they needed themselves or get it somewhere else and not even use our interfaces in the first place. Point 3 & 4: "By the same token, you cannot control the extension points. Unlike class methods which can be marked virtual, there is no way to indicate on an interface which methods are safe to override." "Since all of your methods can only accept the interface IMoney, you cannot relie on the user to pass in instances of Money. By your contract, they can pass in any object that supports the interface. This means you cannot access any property or method marked internal." Again, this project is not an attempt to build an extensible class library. Our primary goal is to provide some core functionality, separate the interfaces from the implementation and publish the interfaces for consumption. Therefore, anything that is needed for a client to code against should be provided in the interface. A good example of this is the ADO.NET interfaces. If we code everything against a SqlServer or Oracle implementations of the core data interfaces we will have to opportunity to override some base methods but the tradeoff in doing so is that we will have brittle software because we can not change the backend database without having to re-write the software. Alternatively, if we know that there is a possibility of a future database change, we can code directly against the provided interfaces and have a higher level of flexibility. Point 5. "Why are you using a custom interface called IAddable instead of overloading the addition operator? Oh right, because interfaces don't support it." You are right. In the .NET framework there are many interfaces precisely for the same reason such as IComparable and IEquatable. Also, if you think about it Microsoft and the development community as a whole are moving towards a service oriented architecture (SOA) approach which is in essence the separation of implementation and interface. We are doing the same thing by providing functionality through an interface and "hiding" the implementation, just a WSDL gives us an interface to interact with web services. I think we would be hard pressed finding someone who advocates doing away with this architectural approach (or maybe not). In closing, I appreciate the opportunity to have dialog and explore this topic in depth. I realize that this subject treads on some people's fundamental beliefs in software design approaches and there are evangelists on both sides but I am always open to any ideas and try to listen to every argument with an open mind. Anyone who claims to know all the answers is either delusional or pulling your leg and we all are all just here to learn from each other. On that note, I would enjoy the opportunity to further investigate your thoughts on "lessons learned" from the COM era that you feel are being ignored in this article. I am the first to admit there are upsides and downsides to every decision made. In order to have a productive dialog to this point I would appreciate of any more specific criticisms of the approach in this article that we could discuss. Thanks, -Matt
Jonathan AllenPosted Nov 3, 2006, 7:01 PM
This goes completely against all of the guidence Microsoft and others have been producing since .NET was released. Have you learned nothing from the COM era? 1. Your solution doesn't support versioning. You cannot add new properties or methods without making a breaking change to the interface. 2. Your solution isn't easily extensible. By using interfaces for everything, users cannot inherit from your implementations. They have to either reimplement everything from scratch or write wrapper classes. 3. By the same token, you cannot control the extension points. Unlike class methods which can be marked virtual, there is no way to indicate on an interface which methods are safe to override. 4. Since all of your methods can only accept the interface IMoney, you cannot relie on the user to pass in instances of Money. By your contract, they can pass in any object that supports the interface. This means you cannot access any property or method marked internal. 5. Why are you using a custom interface called IAddable instead of overloading the addition operator? Oh right, because interfaces don't support it. Jonathan Allen