принцип единой ответственности и читабельность кода

Пытаясь придерживаться правила единой ответственности, мои классы стали выглядеть так

$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'
                                        )
                                    )
                                )
                            )
                        )
                    )
                );

Это только один образец. На первый взгляд все это выглядит круто, поскольку предоставляет очень простые и проверяемые классы. но, как вы можете заметить, читабельность или удобство использования кода отстой. Мне нужно написать бесчисленное количество строк кода даже для обработки простой инициализации загруженного файла (как показано в приведенном выше коде).

Я начал чувствовать, что что-то не так, и я неправильно понял концепцию принципа единой ответственности.

Это то, как обрабатывается чистое ООП с единой ответственностью за каждый класс, или я ошибаюсь?


person user728650    schedule 13.02.2020    source источник
comment
Ты далеко.   -  person Sherif    schedule 13.02.2020


Ответы (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 Pattern. Factory Method Design Pattern на самом деле создает другие объекты. Предполагая, что у вас есть реализация шаблона фабричного метода, которая будет отвечать за создание объекта ImageFile, поскольку ProductImage имеет зависимость ImageFile. Предположим, что вы импортировали все необходимые классы в следующий фрагмент кода:

<?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

Надеюсь, это поможет вам! Удачного кодирования!

person unclexo    schedule 13.02.2020
comment
дядюшка спасибо. супер информативно и очень понятно. только один вопрос, однако, использование статических методов очень осуждается в блогах промоутерами ООП. Можно ли использовать статический метод на фабриках? - person user728650; 13.02.2020
comment
Прежде всего, добро пожаловать! Я использовал его для простоты. Статический контекст легче и читабельнее, чем контекст объекта. Позвольте мне сказать вам одну вещь, что самые популярные фреймворки PHP, такие как Zend, Symfony, используют это много раз. Существует простой недостаток использования статического метода, который заключается в том, что модульное тестирование становится немного сложнее. Но обратите внимание на такой фреймворк, как Laravel, они часто его используют, но также предоставляют средства для тестирования статического метода. Я думаю, вы поймете. - person unclexo; 13.02.2020
comment
@ user728650, это отличное наблюдение, и, пожалуйста, поймите, что шаблон Static Factory полностью отличается от шаблона Factory Method в ГоФ. В шаблонах GoF нет статических методов. - person jaco0646; 13.02.2020