The visibility concept (eg public, protected, private, etc) is overdue for a complete overhaul.
Visibility specifies what code can see/invoke other code, and by doing so, can helps define module boundaries in software.
The four level system used in Java/C# [public, protected, package/assembly, private] is based on an outdated one-dimensional spectrum between self and other. Furthermore, the protected modifier is fixated on the (now declining) importance of class inheritance.
Multiple APIs for Multiple Audiences
In typical enterprise-scale code I work with today, different partly-overlapping sets of methods on a class are called by:
- Application code
- Test Code
- Hibernate persistence code
- Spring Dependecy Injection code
Different methods of a class are written with a particular client, or audience, in mind. The current visiblity systems, which deliniate a spectrum between self and other, cannot express this.
We need a way to say “my persistence layer and my unit tests can call setId() on my domain object, but on one else”.
Make protected a configurable, multi-audience modifier
The idea behind protected is to make the member visible to a priviliged subset of code in the ‘outside’ world, ie subclasses. But nowday, there are so many other reasons why outside code should have differeing levels of access: architectural layering, infrastructure vs application code, aspects such as serailisation or transactional behaviour. In practice, we make everything public and eschew the useless protected level.
We can fix this by making protected accept parameter(s) specifying what code is included or excluded from access.
//equivalent to protected(Subclass)
//can be called by any package or subpackage of com.mycompany
//can be called only by packages com.mycompany or com.myothercompany
//can be called by anyone except subpackages of com.mycompany
Of course, writing the allowed calling classes out above every method would be tedious. Aliasing is needed:
Hibernate = protected(org.hibernate)
In fact, the Java tool Macker enforces visiblity above the language level, because the language-level mechanisms are no longer up to the job.
private is the default
The default visiblity of a member should be private, not package (Java) or internal (ie assembly in C#), to match the default setting most developers actually use in reality.
Its probably too late for Java/C#, but improvements is needed in the next generation.