与src同级的文件夹的PSR-4命名空间约定


PSR-4 namespace conventions for folders on same level as src

当前PSR-4的约定是将src文件夹命名为Vendor'Package。然后使用目录结构对其中的任何文件设置名称空间。所以

src/Model/MyModel.php
使用

namespace Vendor'Package'Model;
class MyModel {...}

这对于src文件夹内的任何文件夹都是直观的,但是与src相同级别的文件夹的约定是什么?例如tests, public, config

(我理解有些人会评论命名空间测试的意义,但想象一个大型项目有许多单独的包,每个包都有自己的测试,但有可以在包之间重用的公共测试。)

我看到了使用Vendor'Package'Tests的建议,但对我来说,遵循src惯例,这给人的印象是src中有一个Tests文件夹,事实并非如此。虽然如果 src中的Tests文件夹,那么这些命名空间会冲突吗?

名称空间应该对逻辑上和语义上属于的代码进行分组。在我看来,配置、路由器和测试都属于整个应用程序的一部分,因此我的配置倾向于让它们都共享命名空间:

autoload: { "psr-4": { "Vendor''Package''": [ "public", "conf", "src" ] } }
autoload-dev: { "psr-4": { "Vendor''Package''": [ "tests" ] } }

当然,通过共享名称空间,这意味着必须对每个工件进行分类(通常根据其"类型"),以防止类名称冲突。例如,Vendor'Package'Foo可能涉及以下相关工件:

  • Vendor'Package'FooTest, tests/FooTest.php
  • 中foo的单元测试
  • Vendor'Package'FooIntegrationTest,一个集成测试,专门覆盖tests/FooIntegrationTest.php
  • 中的foo
  • Vendor'Package'AbstractFoo, src/AbstractFoo.php
  • 中foo的族成员的基
  • Vendor'Package'Fooable, src/Fooable.php
  • 的接口

沿着这些行,您可以考虑将不同类型的代码分离到不同的目录中,而不是一个"包揽一切"的src。对于大型项目,这使得查找特定类型的文件更容易,但对于库或小型应用程序来说,这可能是多余的:

autoload: { 
    "psr-4": {
        "Vendor''Package''": [
            "public", "conf", "lib", "view", "contract", "exception"
        ]
    }
}

至于"约定",我特别发现在源代码和测试之间共享名称空间是方便和容易的,因为当我想测试Foo时,我不必玩弄名称空间来获得它。

// tests/Something/FooTest.php
namespace Vendor'Package'Test'Something;
use Vendor'Package'Test'BaseTestCase;
use Vendor'Package'Something'Foo; // extra work I don't want to do
class FooTest extends BaseTestCase {
    public function testX() {
        $sut = new Foo;
    }
}

在每个测试文件中多出一行,再加上在编写测试时必须找到SUT的认知负荷,意味着编写测试的工作更多,这降低了我编写测试的愿望。因此,您可能会说在源代码和测试之间共享名称空间降低了编写测试的障碍。

最后,源代码组织的问题确实落在每个项目上,以建立一个促进高效开发和合理构建的布局。我想说,试一试也无妨,如果不行就重构。