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

myo*_*yol 3 php composer-php psr-4

PSR-4 的当前约定是将src文件夹命名为Vendor\Package. 然后使用目录结构为其中的任何文件命名。所以

src/Model/MyModel.php
Run Code Online (Sandbox Code Playgroud)

用途

namespace Vendor\Package\Model;

class MyModel {...}
Run Code Online (Sandbox Code Playgroud)

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

(我知道有些人会评论命名空间测试的要点,但是想象一个包含许多单独包的大型项目,每个包都有自己的测试,但具有可以在包之间重用的通用测试。)

我已经看到了使用的建议,Vendor\Package\Tests但对我来说,按照src惯例,这给人的印象是里面有一个Tests文件夹src,但事实并非如此。虽然如果有一个Tests内部文件夹src,然后这些命名空间中会发生冲突?

bis*_*hop 5

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

autoload: { "psr-4": { "Vendor\\Package\\": [ "public", "conf", "src" ] } }
autoload-dev: { "psr-4": { "Vendor\\Package\\": [ "tests" ] } }
Run Code Online (Sandbox Code Playgroud)

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

  • Vendor\Package\FooTest, foo 的单元测试 tests/FooTest.php
  • Vendor\Package\FooIntegrationTest,一个专门覆盖 foo 的集成测试 tests/FooIntegrationTest.php
  • Vendor\Package\AbstractFoo, foo 的家庭成员的基地 src/AbstractFoo.php
  • Vendor\Package\Fooable, foo 之类的东西的接口 src/Fooable.php

按照这些思路,您可能会考虑将不同类型的代码分离到不同的目录中,而不是一个“包罗万象”的目录src。对于大型项目,这使得查找特定类型的文件更容易,但对于库或小型应用程序来说可能有点过分:

autoload: { 
    "psr-4": {
        "Vendor\\Package\\": [
            "public", "conf", "lib", "view", "contract", "exception"
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

至于“约定”,我特别发现在源代码和测试之间共享命名空间既方便又容易,因为当我想测试 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

最终,源代码组织的问题真正落到每个项目身上,以建立一个促进高效开发和合理构建的布局。我会说尝试一个并没有什么坏处,如果它不起作用就重构。