Improving visibility rules for Java & C#

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)

protected

//can be called by any package or subpackage of com.mycompany

protected(com.mycompany.**)

//can be called only by packages com.mycompany or com.myothercompany

protected(com.mycompany, com.myothercompany)

//can be called by anyone except subpackages of com.mycompany

protected(exclude(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.

1 Comment

  1. August 19, 2008 at 11:17 am

    Interesting. Agree with most of the points above. Perhaps schema that have been used in other domains (unix filesystem, for example) could be considered for example (positive and negative).

    Can you suggest a use case for “exclude”? I can’t imagine when that would be necessary.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: