Пример показывает, что бывает, если ему не следовать :) Возвращаясь к вашему. Когда разработчик замечает проблему, он первым делом не меняет иерархию, а переписывает функцию примерно так:
Это, как раз, в тексте есть (см. «Пример иерархии прямоугольника и квадрата и вычислении их площади»). Метод calculateRectangleSquare работает с фигурами рассчитывая на то, что их поведение не будет отличаться, а это не так. Чтоб добиться правильного поведения, нужно править метод и реализовывать различную логику для квадрата и прямоугольника.
Но описано это все, как я писал выше, очень сумбурно.
Что касается примера. Простейший пример нарушения LSP:
sub processOperation
{
if ($operation->type eq 'refund') {
$operation->amount = $operation->amount * -1;
}
…
$operation->process();
}
Нарушение LSP ведет к нарушению OCP т.к. появление еще одной операции, аналогичной возврату, потребует внесения изменений в метод processOperation.
Мой и ваш примеры изложены и подробно разжеваны в книге Дяди Боба «Быстрая разработка программ», в которой SOLID посвящен целый раздел. Можете порекомендовать ее в своем посте и прочесть, если еще этого не сделали.
Проверяем, зависят ли классы от каких-то других классов(непосредственно инстанцируют объекты других классов и т.д) и если эта зависимость имеет место, заменяем на зависимость от абстракции.
Это называется «статическая зависимость».
Судя по тексту, с LSP вы сами до конца не разобрались. Описание этого принципа выглядит очень сумбурно и не содержит информации о том, какой же профит можно получить ему следуя.
Ну а рефакторинг легаси кода — это отдельная история. Фаулер рекомендует сначала покрыть код функциональными тестами, чтоб зафиксировать поведение, и только потом приступать к рефакторингу. Такая задача, действительно, может потребовать серьезных затрат.
Рефакторинг нужно проводить непрерывно. Три недели разрабатываем, неделю рефакторим — это не самый удачный подход. Удачный — сделали фичу (задачу), отрефакторили тесты, отрефакторили код. Время на рефакторинг закладывается при оценке задачи, точно так же, как и время на написание тестов.
Кстати, в подобного рода публикациях почему-то никогда не упоминается квалификация разработчиков, а это не последний фактор, влияющий на качество кода. Квалифицированный, опытный программист никогда не опустится до уровня говнокода просто потому, что не сможет. А неопытный или попросту ленивый всегда найдет отговорку (сроки, прототип, дедлайн), призванную оправдать низкую квалификацию. При этом стоимость разработки будет идентична, а вот в стоимости поддержки выиграет хороший (не путать с идеальным) код — это очевидно.
И не стоит забывать, что из трех ползунков качество должно быть постоянным. Об этом говорят и ДеМарко, и Фаулер и дядя Боб.
Автор, Мартин и Фаулер пишут о том, что следую принципам KISS и YAGNI, необходимо выбирать самый простые алгоритмы и решения, удовлетворяющие текущим требованиям. А использование TDD позволить в дальнейшем, когда требования изменятся и усложнятся, безболезненно внедрять более сложные архитектурные решения а алгоритмы.
А вот о том, что простой код — это говнокод, и тем более, что говнокод обязателен, они точно не пишут, не стоит вводить читателей в заблуждение ;)
А чем, с точки зрения TDD, проект в пару тысяч строк отличается от проекта в десятки тысяч строк? Пользу от TDD можно получить уже на проекте с одним классом и одним публичным методом :)
Что бы там не говорили, но если какой-то модуль начал делать кто-то один, то он его и будет продолжать наращивать из спринта в спринт. И только он может оценить, сколько ему нужно времени на выполнение задачи.
Это противоречит крайне полезному принципу коллективного владения кода.
Для этого необходимо написать тесты, в которых будет детально описано то, что считать достижением требования. Просто говоря, в них описано то, на какую кнопку нажать, и что при этом получится. В команде тесты пишут аналитики.
Здесь речь идет о функциональных требованиях или об автоматизированных тестах? Расскажите подробнее.
Теперь calculateRectangleSquare работает корректно, но нарушает OCP, а причиной этого стало нарушение классом Square принципа LS.
Но описано это все, как я писал выше, очень сумбурно.
Нарушение LSP ведет к нарушению OCP т.к. появление еще одной операции, аналогичной возврату, потребует внесения изменений в метод processOperation.
Мой и ваш примеры изложены и подробно разжеваны в книге Дяди Боба «Быстрая разработка программ», в которой SOLID посвящен целый раздел. Можете порекомендовать ее в своем посте и прочесть, если еще этого не сделали.
Это называется «статическая зависимость».
Судя по тексту, с LSP вы сами до конца не разобрались. Описание этого принципа выглядит очень сумбурно и не содержит информации о том, какой же профит можно получить ему следуя.
И не стоит забывать, что из трех ползунков качество должно быть постоянным. Об этом говорят и ДеМарко, и Фаулер и дядя Боб.
А вот о том, что простой код — это говнокод, и тем более, что говнокод обязателен, они точно не пишут, не стоит вводить читателей в заблуждение ;)
Это противоречит крайне полезному принципу коллективного владения кода.
Здесь речь идет о функциональных требованиях или об автоматизированных тестах? Расскажите подробнее.