Как соблюдать принцип "открыто-закрыто", когда у вас меняется бизнес-логика
Мы делаем некоторые большие изменения в нашей системе, и я хотел бы знать, как лучше реализовать эти новые правила бизнес-логики, соблюдая принципы SOLID:
Принципы Open / Closed гласят: "Открыто для расширения, но закрыто для модификации", хорошо, но как я могу сделать модификацию? Я имею в виду, я не хочу сохранять старую бизнес-логику, и в моем понимании "расширение" в основном означает "добавление кода", а не "изменение кода", так что я понял неправильно?
3 ответа
Два больших вопроса:
О каких изменениях мы говорим здесь?
Какой у вас есть существующий код? Это уже соответствует каким-либо твердым принципам?
Предположим, нам нужно внести некоторые изменения в хорошо спроектированное существующее приложение. Рассмотрим, возможно, приложение для расчета заработной платы. У нас может быть Interafce (это только надуманный пример)
public Interface EmployeeContract {
public int computeSalaryForMonth(int month);
}
и у нас есть реализации:
public class SalesContract implements EmployeeContract {
public int computeSalaryForMonth(int month){
// computation involving sales figures and base salary
}
}
public class HourlyContract implements EmployeeContract {
public int computeSalaryForMonth(int month){
// computation involving hours worked and overtime payments
}
}
Теперь все остальные части приложения кодируются с точки зрения интерфейса.
Теперь мы можем добавлять новые виды контрактов, не меняя существующий код, мы открыты для расширения и добавления, возможно, довольно сложной новой бизнес-логики.
НО это потому, что оригинальный дизайнер ожидал такого рода изменений, добавляя новые типы ежемесячных контрактов. Не так хорошо, если бы мы хотели принять на работу сотрудников, которые получают зарплату еженедельно? Теперь наш интерфейс не подходит, мы должны изменить его, и эффекты будут распространяться через другой код.
Реально, программное обеспечение не будет открыто для безболезненного изменения произвольной бизнес-логики, и, действительно, попытка быть гибкой заранее может поглотить много усилий. Однако обратите внимание, что, хотя в моем примере интерфейс не так гибок, как нам сейчас нужно, поскольку интерфейс - это точка соединения, очень легко идентифицировать части кода, которые необходимо изменить.
Резюме: в вашей ситуации:
- Понять структуру существующего кода и его гибкость. Примите, что некоторый код нужно будет изменить, и неудивительно, что значительные изменения в бизнесе могут потребовать значительных изменений в коде.
- Структура обычно помогает с удобством сопровождения, поэтому при добавлении нового кода обращайте внимание на структуру. Обеспечьте "брандмауэры" в своем коде, кодируя интерфейсы, соблюдая баланс между выполнением работы и возможностью расширения.
Идея Open/Closed заключается в том, что если вам нужна другая бизнес-логика, вам нужно создать новый класс бизнес-логики.
Однако основной мотивацией для этого является то, что вы не хотите влиять на существующий код, проводить повторное тестирование, получать подтверждение снова и т. Д. Если бизнес-логика, которую вы используете, в корне изменилась, и вы бы изменили все ссылки на новый объект и устаревший старый, в этом случае было бы приемлемо повторно открыть объект для модификации. Ключом является то, что (1) вам все равно понадобится повторно протестировать весь код, и (2) старый объект нигде не будет использоваться.
HTH, Джеймс
Открыто-закрытые принципы означают, что вам не нужно изменять текущий код, поэтому он ЗАКРЫТ для модификации, но для выполнения новых требований вам необходимо расширить код с помощью подклассов, реализации интерфейсов, разработки шаблонов, чтобы ваш код был ОТКРЫТ для этих действий. Конечно, во время рефакторинга вы столкнетесь с необходимостью ИЗМЕНИТЬ код, но вы должны сделать это, чтобы удовлетворить OSP.
Например, вместо создания новых объектов аналогичного объекта, разбросанных по коду, вы можете создать Factory Method. Когда новый requiremet приходит, чтобы добавить один новый объект, ваш код будет ЗАКРЫТ для модификации (нет новых экземпляров в коде), но ОТКРЫТ для модификации (расширение Factory Method).