Re: Proposed refactor of standard (and a major technical problem found with lower-casing namespaces)
| From: | David Zülke | Date: | Fri, 07 Aug 2009 20:06:46 +0000 |
| Subject: | Re: Proposed refactor of standard (and a major technical problem found with lower-casing namespaces) | ||
| References: | 1 | Groups: | php.standards |
| Request: | Send a blank email to standards-+get-84@lists.php.net to get a copy of this message | ||
On 07.08.2009, at 19:51, Greg Beaver wrote:
Attachment: [application/pkcs7-signature] smime.p7s
Hi,Hi Greg,
First off, this email is longish. It has 2 sections, the technical problem with the standard, and a concrete proposal for a better standard. The standard is after the line of asterisks.I'm packing for my vacation right now, so this mail is shortish... I can reply in more detail (and answer questions) when I'm back in around a week.
Fatal error: Cannot use pear2\test as test because the name is already in use The problem? PHP's namespaces are not case-sensitive, but autoload translation to paths *is* case-sensitive on unix OSes. Design a standard that mixes case and *BEWM* strange fatal errors that the unaided eye may not be able to detect a reason for.How is that specific to our implementation? It happens either way, whether we mandate lowercase or not.
What this leaves us with is a few things that absolutely everyone agrees upon: 1) namespace separator => path separator 2) every vendor has a lower-cased vendor top-level namespace 3) all classes begin with upper-case characters <-- As PHP 6 approaches I wonder how this plays with languages like Korean that don't have upper/lower case? 4) Interfaces must be suffixed with "Interface"I do not agree on 4) as explained in another message some weeks ago. I'd like it to be "should", not "must", because it is not essential for neither interoperability nor a common autoloader.
7) Abstract classes suffixed with "Abstract" <-- several off-list issues raised for suffixing with "Abstract" include "what if I later decide it's not abstract? I have to break BC to rename it" and "how does one name the sub-classes? ex: pear2\Pyrus\PackageAbstract subclass pear2\Pyrus\Package\Xml or pear2\Pyrus\PackageAbstract\Xml - the first has no obvious connection, the second just looks weird. pear2\Pyrus\PackageXml results in every file in 1 directory, which forces a flat organization (directories are good for organizing things)"I'm leaning in the same direction, although MWOP was correct in pointing out that that barely ever happens once a package is stable.
*****************************************************************
For these reasons, I'd suggest splitting the standard into two segments. The new standard would start with #1-4 with status "stable", and a proposed best practices would start with #5, status "alpha" meaning it may change. The new standard could look like this:
=====
Requirements and restrictions:
(1) Each vendor shall define its own top-level namespace using lower-cased alphanumeric characters
(2) All code shall be organized into packages, each contained within their own second-level directory. For example:
pear2/
Pyrus/
SimpleChannelServer/
Packages are defined exclusively by this top-level directory.
(3) All classes should have names beginning with an upper-cased English character between A and Z. Class names should reflect the relative path within their vendor and package For example: the file pear2/Pyrus/Main.php will contain the class pear2\Pyrus\Main (namespace pear2\Pyrus, class Main)
That's too many shalls and shoulds. In contrast...
(4) All interfaces must have the suffix "Interface." For example, an interface for "Registry" from vendor "pear2" in the package "Pyrus" will be named "pear2\Pyrus\RegistryInterface"... this is an unnecessary "must", because from a purely technical point of view, it doesn't matter for our purpose.
(5) All class-based packages should be designed for autoloading, and should not load dependencies directly using the include, include_once, require, or require_once statement, or any customized loaders. The work of loading a dependent file shall be done either by an autoloader or by the consumer of the package.Another shall that has to be changed to "must". The entire point of the proposal is to have a unified structure with a few basic rules that allow any project that sticks to the standard (or the "must"s anyway) to use a common autoloader which eventually could be implemented in PHP itself.
The draft best practices could look like: ===== (1) Every package that throws exceptions should provide a base exception class. This may be an interface that other exceptions within the package implement.I explained in my other message how that is not universally useful. Consider a small library where the individual parts cannot be used independently of one another. It'd be utterly pointless for all of them to have exceptions that nobody needs. Mandating a base exception on a "project" level or so is more reasonable. A simple library (http://phpcouch.org/ is my example) would have one "global" exception, where as more componentized stuff like ZF offers one per package.
(2) Abstract classes should have the suffix "Abstract." For example, an abstract class for "Registry" from vendor "pear2" in the package "Pyrus" would be named "pear2\Pyrus\RegistryAbstract"Yes. For Interfaces it should be the same. In general, we need to separate between things that are essential for interop (e.g. case, structure, exceptions) and things that are good best practices (e.g. Interface and Abstract suffixes). And then use "must" for the former category and "should" for the latter. - David
Attachment: [application/pkcs7-signature] smime.p7s