Protected vs Private

The Symfony and Doctrine2 project recently changed protected functions and properties into private in order to provide a well defined public API. While I agree with the principle, this has some bad side effects for FLOW3 code.

In the TYPO3 project we learned the Open / Closed Principle the hard way. Because TYPO3 started as a PHP3 project more than ten years ago, all methods and properties were public by default – and extension developers made heavy use of many functions of the TYPO3 core which were never meant to be public. This is actually one of the reasons we finally decided to rewrite TYPO3 from scratch – because any refactoring of the core was like playing with the fire, as we couldn't know how many extensions were relying on the part we were going to change.

The least we could do was using the public and protected keywords to document which code parts could be used by other classes. However, sub classes still might rely on protected methods which are not meant to be part of the publicly supported API. The logical next step is to mark those methods as private. Problem solved?

When we discussed using the private and final keywords two or three years ago, we concluded that this wouldn't solve our problem completely: there are still public methods (which need to be public because they are used by other classes in our framework) which we don't consider part of the public API. So as we cannot prevent usage of these functions technically, we chose to go for a white list approach: all classes, methods and properties which we consider part of the public API (and hence make sure that we stay backward compatible) are labeled with an @api annotation in the respective doc comment. Our API documentation contains only those code parts and give you a clear overview of what API you may use.

But why not use final and private keywords for the rest? Because it gives us some headaches with our proxy mechanism. As you might know, FLOW3's AOP implementation (and since recently also our DI support) relies on proxy classes and hence the ability to extend and override the original class. This works fine as long as your class is not final and its methods are either public or protected. While there certainly is a way to circumvent this (I know one, but it makes me shiver), life would be so much easier without private and final.

So the question remains: should FLOW3 support and use private / final methods and classes? Or do @api annotations make more sense to you?

Leave a reply