Подтвердить что ты не робот

Принцип Open/Closed - Как назвать новые версии?

Я пытаюсь понять принцип Open/Closed (в моем случае для PHP, но это не имеет особого значения).

Я понимаю, что класс никогда открыт для модификации. Только для исправления ошибок. Если бы я хотел добавить новый класс в класс, тогда мне нужно было бы создать новый и расширить "старый" класс. Это единственный способ добавить к нему новый код.

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

Но как это работает на практике? Я имею в виду, предположим, что у меня есть следующий класс:

class MyObject
{
    public function doSomething()
    {
        echo 'Im doing something';
    }
}

Итак, где-то я, вероятно, создаю экземпляр этого класса:

$obj = new MyObject();

Но потом я решил, что хорошо иметь другой метод в этом объекте. Поэтому я тоже могу сделать что-то еще. Согласно OCP, я не могу изменить класс. Так что я должен создать новый, который простирается до старого один?

Первая проблема. Как я могу назвать новый класс? Потому что это не совсем новый объект. Подобно. Пользовательский объект является объектом User. Я не могу внезапно дать ему совершенно разное имя только потому, что ему нужен другой метод. Во всяком случае, я создаю новый класс:

class MyNewObject extends MyObject
{
    public function doSomethingElse()
    {
        echo 'Im doing something else now';
    }
}

Теперь это также означает, что мне нужно изменить строку кода, где я создал экземпляр класса "MyObject" и заменил его классом "MyNewObject", правильно...? И если это сделано в более чем одном месте, тогда мне нужно выполнить поиск по моему исходному коду... (Подумайте о методе в классе контроллера, который почти всегда использует ключевое слово "новое" для создания экземпляров определенных классов).

То же самое относится и к наследованию. Я должен найти каждый класс, наследующий старый класс, и должен заменить его новым классом.


Итак, в основном мои вопросы:

Как вы называете новые классы, которые имеют новые методы? Просто потому, что я добавил некоторые новые функции, не означает, что я могу дать классу совершенно новое имя...

И что, если "старые" классы создаются (или унаследованы) из нескольких мест. Тогда мне нужно будет найти все эти места... Где выигрыш?

4b9b3361

Ответ 1

Принцип Open Closed не предназначен для использования в качестве системы контроля версий. Если вам действительно нужно внести изменения в класс, то сделайте эти изменения. Вам не нужно создавать новые классы и изменять все места, которые создавали старый.

Точка открытого закрытого принципа заключается в том, что хорошо спроектированная система не должна требовать от вас изменения существующей функциональности, чтобы добавить новую функциональность. Если вы добавляете новый класс в систему, вам не нужно искать по всему вашему коду, чтобы найти места, где вам нужно ссылаться на этот класс или иметь специальные случаи для него.

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

Ответ 2

Я бы сказал, что добавив функцию, вы не изменяете поведение класса.

Во всех случаях, когда doSomething() в настоящее время вызывается в вашем приложении, просто добавив doSomethingElse() в класс, это не будет иметь никакого эффекта. Поскольку вы не меняете doSomething(), поведение такое же, как и раньше.

Как только вы определите, что ваша реализация doSomething() не разрезает ее при определенных обстоятельствах, вы можете расширить класс и переопределить doSometing(). Опять же, оригинал по-прежнему ведет себя так же, как и всегда, но теперь у вас есть новый doSomething() для работы с ним.

Я понимаю, что это противоречит строгим определениям open/closed, но это реальный мир и что я интерпретировал этот принцип в своем коде.

Ответ 3

Вам нужно создать конструктор в классе MyNewObject, который вызывает конструктор родительского класса:

function __construct() {

    parent::__construct();

}

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

Затем вы также можете переопределить любую функцию в родительском классе (если она конечно не отмечена окончательно).

Итак, вы можете сделать:

$newObj = new MyNewObject();

$newObj->doSomething();

$newObj->doSomethingElse();