Hi all,
Two issues have been at the back of my mind regarding service names, and now is the time to bring them up. These issues are related to each other.
First, it's hard to tell what services a package defines, and which ones it modifies. In order to find that out, you need to walk through the configuration `define()` code and examine it directly for `$di->set(...)` calls, and the then examine the `modify()` code for `$di->get()` code.
Second, we currently name shared services in a project container pretty loosely. We have a "logger", a "web_responder", "cli_dispatcher", and so on. This loose naming means it may be tough to combine services from different packages. If VendorFoo.Package creates a "zim" service and VendorBar.Package also creates a "zim" service then they will be in conflict.
I'd like to discuss our options related to these two issues.
* * *
I think the second problem is the easier one to solve. I propose that from here on we name services *for the package in which they are defined*. The service name should begin with the Composer-style package name, be followed by a colon, and then match ([A-Za-z][A-Za-z0-9_]*) in the name (so that the latter part can mimic variable name).
For example, the Aura.Web_Kernel package currently defines four services:
- `$di->set('web_request', ...)`
- `$di->set('web_response', ...)`
- `$di->set('web_router', ...)`
- `$di->set('web_dispatcher', ...)`
Under the new proposal for names, they would become:
- `$di->set('aura/web-kernel:request', ...)`
- `$di->set('aura/web-kernel:response', ...)`
- `$di->set('aura/web-kernel:router', ...)`
- `$di->set('aura/web-kernel:dispatcher', ...)`
FWIW, I tried several variations, and this is the one that looks least like a class name. Because project config files will have a mix of class name references and service name references, I want them to be easily distinguishable. The other variations included ...
- Aura\Web_Kernel\(Response|Request|Router|Dispatcher)
- Aura\Web_Kernel:(response|request|router|dispatcher)
- Aura\Web_Kernel.(response|request|router|dispatcher)
- Aura.Web_Kernel.(response|request|router|dispatcher)
- aura/web_kernel.(response|request|router|dispatcher)
- aura.web_kernel:(response|request|router|dispatcher)
- aura.web_kernel.(response|request|router|dispatcher)
... and so on. If you feel strongly about one of those variations, please speak up.
Thoughts on this or any other service naming convention?
* * *
That leaves us with the first problem, that of documenting what services are needed, which are defined, and which are modified by a package. A quick Google search does not reveal how Zend, Symfony, et al. are handling this, if at all.
One idea is to co-opt Composer again, and add an "extra:aura:services" element like so:
"extra": {
"aura": {
"services": {
"provides": {
"vendor/package:foo": "Vendor\Package\Foo",
"vendor/package:bar": "Vendor\Package\Bar"
},
"modifies": [
"other/package-baz:dib"
],
"requires": [
"another/package-zim:gir",
"and-yet/another:irk"
}
}
}
}
The "services" key is where we list the services.
The "provides" key lists the services provided by the package. It is a series of key-value pairs where the key is the service name, and the value is the class or interface exposed by the service.
The "modifies" key is a sequential array of services modified by the package. It does not specify a class name because we should probably not be changing the class or interface of the defined service. (The package may or may not use the modified services.)
The "requires" key is a sequential array of services from other packages that this package needs.
This seems pretty straightforward to me, and easy to work with, but there is at least one drawback. The composer.json definition is somewhat distant from the config/*.php files where the services are defined; if the configured services change, then you also need to change composer.json, and that can be a hassle.
One alternative would be to introduce an annotation for the config file docblocks, perhaps `@provides-service`, @modifies-service`, and `@requires-service`. That would keep the documentation closer to the actual configuration code, but it becomes somewhat harder to parse, and would probably require wider community involvement on standardizing the format.
Thoughts on these or or other service documentation ideas?
* * *
Thanks everyone!
--
Paul M. Jones
pmjo...@gmail.com
http://paul-m-jones.com
Modernizing Legacy Applications in PHP
http://mlaphp.com