Профиль пользователя заблокирован сроком с 10 апреля 2022 г. и навсегда по причине: систематические нарушения правил сервиса
Ответы пользователя по тегу SOLID
  • Как провести соответствие между строкой и классом с точки зрения SOLID?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Это всё очень плохо.
    В первом варианте человек должен знать, как мяукают кошки, а в последнем "правильном" варианте человек трогает не кошку, а кошачий голос(?!).
    В "идеальном" варианте опять же выбирается не животное, которое надо погладить, а его голос.

    Чтобы следовать принципам солид, надо понять в первую очередь ЗАЧЕМ это всё делается.
    А делается это для того чтобы уменьшить связность. Чтобы класс, использующий какой-либо функционал, не знал деталей его реализации. И, соответственно, мы могли бы менять реализацию без опасения поломать что-то в классе-пользователе.

    При этом extends, кроме как от абстрактного класса, эту связность всегда увеличивает.
    И его надо избегать. А использовать принцип Composition over inheritance. То есть нужный функционал получать не наследованием, а передачей независимых функциональных модулей в виде параметров.

    Соответственно, нам надо сделать иерархию: голос - животное - потрогать.
    И вот теперь у нас хоть голос, хоть животное, будут открыты для каких угодно изменений, до тех пор пока они поддерживают публичный контракт.
    / ******* голоса *******/
    abstract class VoiceEngine {
    	public function getVoice() {}
    }
    class CatVoiceEngine extends VoiceEngine {
    	public function getVoice() {
    		return "Meow!";
    	}
    }
    class DogVoiceEngine extends VoiceEngine {
    	public function getVoice() {
    		return "Bark!";
    	}
    }
    class HumanVoiceEngine extends VoiceEngine {
    	public function getVoice() {
    		return "Да пошёл ты!";
    	}
    }
    / ******* животные *******/
    abstract class Animal {
    	public function __construct(public VoiceEngine $voiceEngine) {}
    	public function say() {
    		echo $this->voiceEngine->getVoice();
    	}
    }
    class Cat extends Animal{}
    class Dog extends Animal{}
    class Human extends Animal{
    	public function touchAnimal(Animal $animal) {
    		$animal->say();
    	}
    }
    / ******* исполнение *******/
    $cat = new Cat(new CatVoiceEngine());
    $dog = new Dog(new DogVoiceEngine());
    $human = new Human(new HumanVoiceEngine());
    $human->touchAnimal($cat);
    $human->touchAnimal($dog);
    $human->touchAnimal($human);


    После того как я, раздуваясь от гордости, написал этот ответ, до меня вдруг дошло что на вопрос-то я так и не ответил.
    Соответственно, задачу выбора животного возлагаем на отдельную сущность:

    class AnimalFactory {
        public static function create($type) {
            return match($type) {
                'cat' => new Cat(new CatVoiceEngine()),
                'dog' => new Dog(new DogVoiceEngine()),
                'human' => new Human(new HumanVoiceEngine()),
            };
        }
    }
    $human = new Human(new HumanVoiceEngine());
    $human->touchAnimal(AnimalFactory::create('cat'));

    В итоге мы вернулись к тому же кейсу (match - это улучшенный case), но при этом у нас всё разделено, и каждый класс занимается строго своим делом.
    Ответ написан
  • Что такое SOLID и как его можно использовать в веб-разработке?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Весь солид сводится к решению одной проблемы:

    внесли изменения в один кусок кода, и у нас упал другой, никак, на первый взгляд, с первым не связанный

    Следовательно, использовать его можно только если осознаешь ответственность за работу своего приложения.
    При веб-разработке по системе "отдал заказчику и забыл" практически не применяется.

    Понимания можно достичь прочитав книжку Роберта Мартина
    Ответ написан
    3 комментария