Sylvain Wallez wrote:
Sure. But then, one way or the other, the contract of the class with its subclasses is changed, and the subclasses are broken !Yepp, but I think in this case it's ok, the subclasses have to be adjusted accordingly. You can't make implementations 100% compatible and declaring instance members as private doesn't help in open source.
Has someone followed the changes to Cocoon.java regarding the component manager. It started as private was changed to protected and then changed to public by someone who needed it (also it was never meant to be public!). But as it's open source with so many developers, someone changes it and in most cases this goes unnoticed. Then someday someone noticed that and changed it back to protected. Later on it was changed to public again and this went on for a while! Now, finally we have a public getComponentManager method, although this was never meant to be publically available.
Putting it short: even if the original author thinks that something is really only private, someone else has a different opinion and changes it. But for whatever reason, it might be unavoidable to change the implementation breaking this.
I think there's a misunterstanding about the "audience" of the contract. We need some information to have the "public" Java access modifier because we need that information in other packages of the org.apache.cocoon code base for Cocoon's internal machinery. And access modifiers come an go as we, Cocoon developpers, need them for the Cocoon core. But some of these information, even if accessible from a compiler point of view, are not considered as generally available to the wider audience of Cocoon users.
Take another example : CocoonComponentManager.getCurrentEnvironment(). We need this method to have the "public" access modifier because we need this information to implement SitemapSource and other pipeline machinery. But we all agree that using it for "normal" components is a hack that should be prohibited.
Now imagine the following story : an innocent Cocoon user downloads Cocoon 2.1, digs the javadoc and finds this method. "Cool", he says, "this public method gives me access to the Environment that provides so much interesting data. I'll use it there, and there, and there". Now we, Cocoon devs, decide to refactor the internal pipeline machinery for some reason, and finally no more need this method. At we consider its use as an internal hack, we remove it. Now our innocent users sees the new Cocoon 2.1.1 release which is told to be faster. "Cool", he says, "let's drop the new jars in my WEB-INF/lib". And bing bang, NoSuchMethodError all over the place because the method he used has disappeared.
As, you can see, there's a big difference between the "public" access modifier required by the Java syntactic rules, and the public API that is safe for "innocent users" to use. And that's why I'm proposing : a restricted official public API. People using it will know that it will never change. And if it has to (e.g. Composable --> Serviceable), then new classes will be created. And people using syntactically public but not officially public members and methods will be warned that doing so may lead their code to be broken in the future.
Agree, but that's theory : as long as a member or method is accessible, you can be sure someone will use it.
Yes, why not? And in the rare cases where the implementation changes the subclass will break sometime. But as the contract is defined by the interface the original class does still the same task as before but with a different implementation. So the subclass could be changed accordingly. Ok, this is theory as well, I know. It's even academic. How often does an implementation change? I think it's an acceptable risk.
Once again, this is totally acceptable withing the Cocoon code base. I make a change to a class member, save the file, and Eclipse tells me instantly where additional changes are needed. But only in the Cocoon code base, and not in world-wide user's code.
A solution to this may be to define those methods and members that we, Cocoon developpers, consider to be safe for use outside of the Cocoon code base. Xalan has a feature for this : they embed some <meta> tags in the javadoc that is later used to produce the Javadoc. This allows to build a public API where some of the class/members/methods that are public/protected from a syntactic point of view are removed from the produced documentation.Yes, this is a good idea, but I'm not sure if it's practical. It requires alot of discipline for everyone. But we could try it with the default "internal" or "experimental".
See e.g. the ExtensionHandler class [1] and the resulting Javadoc [2]. The values of the <meta> tag can be general, internal, advanced; experimental.
By using this kind of feature (@usage would be better than <meta name="usage">), we can cleanly separate what we consider as "publicly available" (and that we guarantee to last) from what we make public for the needs of Cocoon development.
Yep : by having default to "internal", we hide from the "official" javadoc every item that is not explicitely public. And once someone adds a "@usage public" to an item, then it's forbidden to remove it.
We could then have a full javadoc, as of today, and a restricted "official API" javadoc, based on these @usage tags. This official API will also be far more lightweight and so less frightening for newcomers. It also has the additional benefit for us, lazy developpers, that only official classes and methods need comprehensive documentation ;-)
Our users need API stability, and not all public items of our huge code base can be considered as "stable API". That's the whole point. And going through this process of tagging our code base with "@usage" can force us to better design the extensions points of our components.
What do you think ?
Sylvain
-- Sylvain Wallez Anyware Technologies http://www.apache.org/~sylvain http://www.anyware-tech.com { XML, Java, Cocoon, OpenSource }*{ Training, Consulting, Projects } Orixo, the opensource XML business alliance - http://www.orixo.com
