Я понимаю цель принципа открытого-закрытого. Он предназначен для того, чтобы уменьшить риск поломки чего-либо, что уже работает при его изменении, предлагая вам попытаться расширить без изменения.
Однако у меня возникли проблемы с пониманием того, как этот принцип применяется на практике. Насколько я понимаю, есть два способа его применения. До и после возможного изменения:
До: программируйте на абстракции и «предсказывайте будущее» столько, сколько сможете. Например, метод
drive(Car car)
должен будет измениться, еслиMotorcycle
в будущем в систему будут добавлены s, поэтому он, вероятно, нарушает OCP. Ноdrive(MotorVehicle vehicle)
в будущем этот метод вряд ли изменится, поэтому он придерживается OCP.Тем не менее, довольно сложно предсказать будущее и заранее знать, какие изменения будут внесены в систему.
После: когда требуется изменение, расширяйте класс вместо изменения его текущего кода.
Практику № 1 не сложно понять. Однако на практике № 2 у меня возникают проблемы с пониманием того, как подать заявку.
Например (я взял его из видео на YouTube): допустим , у нас есть метод в классе , который принимает CreditCard
объекты: makePayment(CraditCard card)
. Один день Voucher
добавляются в систему. Этот метод не поддерживает их, поэтому его необходимо изменить.
При реализации метода в первую очередь нам не удалось предсказать будущее и программировать в более абстрактных терминах (например makePayment(Payment pay)
, теперь мы должны изменить существующий код.
Практика № 2 говорит, что мы должны добавить функциональность, расширяя, а не модифицируя. Что это обозначает? Должен ли я создать подкласс существующего класса вместо простого изменения его существующего кода? Должен ли я сделать вокруг него какую-то обертку, чтобы избежать переписывания кода?
Или принцип даже не относится к «как правильно изменить / добавить функциональность», а скорее относится к «как избежать необходимости вносить изменения в первую очередь (т.е. программировать абстракции)?