如何在 PHP 7.4 中使用 DocBlocks?

mtw*_*cki 1 php software-design docblocks

一般来说,在 PHP 中使用 DocBlock 是最佳实践之一。它对于以前的 PHP 版本(小于 PHP 7.3 或特别是 7.4)非常有用。它通知开发人员有关类属性类型、预期参数类型和方法返回值(在 PHP 中缺乏严格类型的情况下)。

假设在 PHP 5.6 中,代码如下所示:

namespace App\Service\Catalog\Category;

use App\Entity\Catalog\Category\Category;
use App\Repository\Catalog\Category\CategoryRepository;

class CategoryService
{
    /** @var CategoryRepository */
    private $categoryRepository;

    /** @var int */
    private $currentNestingLevel = 1;

    /**
     * CategoryService constructor.
     * @param CategoryRepository $categoryRepository
     */
    public function __construct(Category $categoryRepository)
    {
        $this->categoryRepository = $categoryRepository;
    }

    /**
     * @param $parentCategoryId
     * @return array
     */
    public function getCategoriesDataByParentCategoryId($parentCategoryId)
    {
        $categories = $this->categoryRepository->getByParentCategoryId($parentCategoryId);
        $categoriesData = [];

        foreach ($categories as $category) {
            $categoriesData[] = $this->getCategoryData($category);
        }

        return $categoriesData;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是在这种情况下,当我们使用 PHP 7.4 时,这些 DocBlocks 不提供任何附加信息:

namespace App\Service\Catalog\Category;

use App\Repository\Catalog\Category\CategoryRepository;

class CategoryService
{
    private CategoryRepository $categoryRepository;

    private int $currentNestingLevel = 1;

    public function __construct(CategoryRepository $categoryRepository)
    {
        $this->categoryRepository = $categoryRepository;
    }

    public function getCategoriesDataByParentCategoryId(int $parentCategoryId): array
    {
        $categories = $this->categoryRepository->getByParentCategoryId($parentCategoryId);
        $categoriesData = [];

        foreach ($categories as $category) {
            $categoriesData[] = $this->getCategoryData($category);
        }

        return $categoriesData;
    }

}
Run Code Online (Sandbox Code Playgroud)

Robert C. Martin 在 Clean code 中写道,对所有方法/变量等使用 JavaDoc(sic!) 是不好的做法,会降低代码的可读性。此外,他说有可能注释 (DocBlock) 不反映指定元素的当前状态(例如,在 DocBlock 中,我们有 int,但变量已更改为字符串)

我查了一下,PSR标准主要只说DocBlock的使用方法和外观,而不是什么时候使用。

你怎么看待这件事?我们应该始终对代码中的所有元素使用 DocBlock 还是仅在特定情况下使用?在这两种情况下,您看到了什么样的优缺点?

vur*_*yss 5

鲍勃叔叔说他的书是对的——使用注释来提供你不能用代码明确表达的信息。如果注释只是重复函数名和参数 - 不需要使用它。正如书中提到的那样,当代码更改使下一个开发人员处于糟糕的境地时,注释往往保持不变。

因此,在注释中表达任何无法用函数名称和变量表达的特定领域规则和策略。

此外,由于 Clean 代码手册主要围绕 Java 语法支持编写 - 在 PHP 中,我们无法在代码中明确声明此方法会在某个地方抛出异常。这意味着我们可以通知 IDE 和开发人员预期异常的唯一方法是使用 @throws 标签。

Java 也支持注解,而 PHP 不支持。这是注释的另一种可能用途。一些框架决定使用它——比如带有路由注释的 Symfony。带有实体注释等的 Doctrine ORM。它们在库中被读取和编译,以提供类似于内置注解的支持。

所以使用 Bob 叔叔在他的书中推荐的注释,由于 PHP 的特性,添加了以下内容:

  • 注释支持(@see Doctrine annotations)
  • @throws 异常标记
  • 任何不能用类/函数/变量名表达的逻辑

还有一种可能的用法是特定于 IDE 或特定于工具的注释,例如:

  • PHPStorm 抑制给定检查
  • PHPMD 抑制给定警告

正如@El_Vanja 所指出的:

  • 您可以更具体地针对预期类型,例如可迭代的内容:@return SomeClass[]@param string[]

  • 我只想明确指出另一种有用的情况,那就是指定数组或可迭代对象的内容,例如“@return int[]”或“@param iterable<SomeModelClass>”,因为“ array` 和 `iterable` 是有点太宽泛的提示。尽管如果通过属性/方法名称明确内容,人们可以很容易地避免使用它们。 (2认同)