One of the primary considerations when building a software platform that other developers based their work on is to maintain backwards compatibility. As the platform grows larger and more complex this can become the major restraining factor when trying to sustain a high development pace.
Once you start to use strict semantic versioning it becomes glaringly obvious that no API changes can be done no matter how small the change or how obscure the class is, unless releasing a new major version. And while releasing a new major version might not be as big a deal as it used to be, it does add additional work, not just internally, but also for any maintainers of third party modules trying to keep their modules up to date.
internal, <internal /> or .Internal?
The typical approach to this problem is to keep your public classes to a minimum and only expose classes that are actually useful to interact with for external developers. Limiting the API is currently done primarily by keeping classes or methods internal. And while we might be high-fiving each other at the office every time we can add the internal keyword to a class, it seems like it is making some of you platform users less happy, some more than others.
Another option is to use the API documenation and explicitly call out the classes and methods that are considered internal. And while this method has been used with some success in the past, such in the case of the EPiServer.DataAccess namespace, it can sometimes be hard to keep track of which APIs are public or not if they are spread out.
For quite some time now we have been discussing better ways to manage these API restrictions. But as always, while you discuss, other people do, and this is exactly what Microsoft has done. In their latest .NET Core platform they have introduced the notion of “Internal namespaces”, which is a specific namespace pattern that indicates that you are now dealing with classes that are not a part of the public API. As this was very closely aligned with our own thoughts we have decided to follow suit and use the same approach.
This means that going forward any class located in a namespace named 'Internal' will not be considered a part of our supported public API. These classes can still be used, they are just not covered by the semantic versioning promise and can therefore change between minor releases without prior warning. Any problem that arise from using it will also not be covered by our usual support.
It should however mean that we can expose more classes as public in our assemblies so that they are easier to use if you really, really need to or for any non-production scenarios such as for unit testing.
This does not imply that everything outside these namespaces will be a part of the public API as there will still be classes and methods that are explicitly documented as being for “internal use” but we will try to keep these to a minimal whenever possible.
When should I start to notice these changes?
There are some areas in CMS and other products where you can already find Internal namespaces, but so far the use has been relatively limited.
In our next major release, Episerver CMS 10, which is just around the corner, you will notice that we have moved a lot of the classes from their current location to these Internal namespaces in an attempt to minimize the weight of our legacy backpack. This will include any classes that we do not consider important for typical use cases or implementations of public abstractions.
So when you upgrade a solution, please be careful and make sure that you don’t accidentaly add any Internal namespaces to your using statements as this may cause you some problems in the future.
That should be public!
Should you find a class or interface that you believe should have remained in the public API, please contact us and tell us why you think this should be the case.