【问题标题】:single responsibility principle and code readability单一职责原则和代码可读性
【发布时间】:2020-05-28 18:40:42
【问题描述】:

在尝试坚持单一职责规则时,我的课程开始看起来像这样

$productImage = new ProductImage(// holds all rules for product image only
                    new ImageFile( // makes sure given file is an image file
                        new ReadableFile( // checks given item is a readable file / permissions check
                            new UploadedFile( // validates given file is uploaded file
                                new FilePath( // validates given string is a valid file path
                                    new Path( // validates for string to be a path
                                        new NonEmptyString( // given string is not empty
                                            '/tmp/xyzk7kjnbrukhg'
                                        )
                                    )
                                )
                            )
                        )
                    )
                );

这只是一个示例。 从表面上看,它看起来很酷,因为它提供了非常简单和可测试的类。但是您会注意到代码的可读性或可用性很差。我需要编写无数行代码,甚至处理上传文件的简单初始化(如上面的代码所示)。

我开始觉得有些不对劲,我误解了单一责任原则的概念。

是如何处理对每个类单独负责的纯 OOP 还是我离题了?

【问题讨论】:

  • 你已经走了。

标签: php architecture solid-principles single-responsibility-principle


【解决方案1】:

您与SRP (Single Responsibility Principle) 完全不同。在您的代码中完全看不到 SRP 的工作方式。没关系,你有他们负责不同工作的课程。可能是或者我猜,它们是通过尊重SRP 来实现的。除了假设之外,您的代码中 SRP 的可见性要少得多。

OOP 中,类依赖于其他类。这是完全正常的。 Dependency Injection 在您的代码中完全可见。但是您不能像构建复杂结构时那样通过构造方法维护Dependency Injection。那应该是以下方式:

<?php

// given string is not empty
$nonEmptyString = new NonEmptyString('/tmp/xyzk7kjnbrukhg');

// validates for string to be a path
$path = new Path($nonEmptyString);

// validates given string is a valid file path
$filePath = new FilePath($path);

// validates given file is uploaded file
$uploadedFile = new UploadedFile($filePath);

// checks given item is a readable file / permissions check
$readableFile = new ReadableFile($uploadedFile);

// makes sure given file is an image file
$imageFile = new ImageFile($readableFile);

// holds all rules for product image only
$productImage = new ProductImage($imageFile);

但这也不是正确的做法。要以正确的方式执行此操作,您需要使用Factory Method Design PatternFactory Method Design Pattern 实际上创建了其他对象。假设您有一个工厂方法模式实现,它将负责创建ImageFile 对象,因为ProductImage 具有ImageFile 的依赖关系。假设你在下面的代码 sn-p 中导入了你需要的所有类:

<?php

class ImageFileFactory implements FactoryInterface
{
    public static function make($string)
    {
        // given string is not empty
        $nonEmptyString = new NonEmptyString($string);

        // validates for string to be a path
        $path = new Path($nonEmptyString);

        // validates given string is a valid file path
        $filePath = new FilePath($path);

        // validates given file is uploaded file
        $uploadedFile = new UploadedFile($filePath);

        // checks given item is a readable file / permissions check
        $readableFile = new ReadableFile($uploadedFile);

        // makes sure given file is an image file
        return new ImageFile($readableFile);
    }
}


// Creates ImageFile instance
$imageFile = ImageFileFactory::make('/tmp/xyzk7kjnbrukhg');

// holds all rules for product image only
$productImage = new ProductImage($imageFile); 

哦!我在SRP 上写了一篇关于媒体的文章。如果你可以阅读它。这是SRP的链接

希望对您有所帮助!快乐编码!

【讨论】:

  • 感谢 unclexo。超级翔实且非常清晰。不过,只有一个问题,OOP 推广者在博客中非常不赞成使用静态方法。工厂里可以用静态方法吗?
  • 首先,不客气!为了简单起见,我使用它。静态上下文比对象上下文更容易和可读。让我告诉你一件事,PHP 最顶级的框架,如 Zend、Symfony 多次使用这个。使用静态方法有一个简单的缺点,即单元测试变得有点困难。但是看到像 Laravel 这样的框架,他们经常使用它,但也提供了测试静态方法的工具。我想你会明白的。
  • @user728650,这是一个很好的观察,请理解Static Factory 模式与 GoF 中的工厂方法模式完全不同。 GoF 模式中没有静态方法。
猜你喜欢
  • 1970-01-01
  • 2010-11-26
  • 2016-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-09
  • 2016-01-21
  • 1970-01-01
相关资源
最近更新 更多