1 / 1 / 0
Регистрация: 03.12.2014
Сообщений: 29
1

Нарушен ли solid ?

12.02.2017, 11:57. Показов 1357. Ответов 11
Метки нет (Все метки)

Привет.

Есть например сущности предметной области Нож и Складной Нож.
Как вы думаете нужно спроектировать классы в этом случае?
PHP
1
2
3
4
5
6
7
8
9
10
11
12
    class Knife{
      public function cut {/* режем */}
    }
    class PocketKnife extends Knife{
      private $opened = 0; // 0/1
      // ...
      public function cut {
        if ($this->opened) {
          parent::cut();
        }
      }
    }
Нарушит ли это Принцип подстановки Барбары Лисков, или я неверно его понимаю ?
Ведь для объекта Knife постусловия после операции cut() например такие:
- лезвие стало менее острым чем было (изменение атрибута самого объекта)
- разрезаемый объект получил урон.

Но если подменять Knife на PocketKnife, и второй не раскрыт, то он и не разрежет ничего, т.е. он этих постусловий не даст, сузит получается, а в принципе сказано - "Постусловия не могут быть ослаблены в подклассе"
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.02.2017, 11:57
Ответы с готовыми решениями:

Нарушен принцип инкапсуляции
Под спойлером ссылка на цитату из книги Хорстмана. Не могу до конца разобраться с этим...вроде...

Нарушен баланс мощности при выводе звука
Доброго времени суток всем ценителям открытого кода! Имеется Lucid, Creative SB Live! Value,...

Выгрзука в Excel из DataGridView. Нарушен порядок столбцов
Здравствуйте. Выгружаю данные из БД на DataGridView. Затем из DataGridView делаю экспорт в Excel....

SOLID
Здравствуйте, стоит ли использовать правила SOLID в маленьких задачках, например в том же шифре...

11
Заблокирован
12.02.2017, 14:12 2
Вообще, тут, по-моему, принцип подстановки Лисков за уши притянут, пред и постусловия -- это терминология контрактного программирования.

Нарушаться, ИМХО, там ничего не нарушается, это зависит от контрактов. Но у вас нарушается именно стиль контрактного программирования, Вы делаете проверки.

Вот цитата:
Необходимо гарантировать, что функции данного класса будут возвращать корректные данные, либо, вообще не будут работать.
https://neerc.ifmo.ru/wiki/ind... 1%82%D1%83

Это, практически, Ваш случай.

Добавлено через 7 минут
Там, насколько я понимаю, упор делается на отсутствии лишних проверок
Программирование по контракту – прекрасный способ документирование кода, отладки, исключения лишних проверок. Например, если в постусловии написано, что метод возвращает неотрицательное число, то нет необходимости проверять число на неотрицательность при извлечении квадратного корня. Все это ведет к повышению надежности, качества и скорости разработки.
В Вашем случае, если постусловие -- нож либо режет либо ничего не делает, значит контракты соблюдаются. Любой нож в конце концов может не разрезать по тем или иным причинам -- слишком тупой, находится в чехле и тп.

Добавлено через 23 минуты
Цитата Сообщение от Valeov Посмотреть сообщение
if ($this->opened) {
хотя, именно принципы контрактного программирования, в вашем случае, таки нарушены. Проверок в подклассах не должно быть.
Я хоть и не особо знаком с темой, но представляю себе это как то так
Код
Knife := Object clone do(
    cut := method(object, if(canCut, object sliced := true))
)

PocketKnife := Knife clone do(
    canCut := false
    open := method(canCut = true) 
    close := method(canCut = false)
    
)

Whinger := Knife clone do(
   canCut := false
   putInCase := method(canCut = false)   
   getOutCase := method(canCut = true)
)

Apple := Object clone do(sliced := false)

apple1 := Apple clone
apple2 := Apple clone

pocketKnife := PocketKnife clone
whinger := Whinger clone


pocketKnife cut(apple1)
whinger cut(apple2)

writeln(apple1 sliced)
writeln(apple2 sliced)

pocketKnife open
whinger getOutCase

pocketKnife cut(apple1)
whinger cut(apple2)

writeln(apple1 sliced)
writeln(apple2 sliced)


#>>>> false
#>>>> false
#>>>> true
#>>>> true
0
Эксперт .NET
9443 / 6815 / 1094
Регистрация: 21.01.2016
Сообщений: 25,905
12.02.2017, 14:30 3
Valeov, по-моему, данный принцип так же оговаривает ожидания вызывающего кода в отношении вызываемого. Если вызывающий код допускает, что метод cut() сделает ничего (или ему просто пофигу на результат), а сам метод таки связан с резанием, то принцип подстановки Лисков не нарушен.
1
1 / 1 / 0
Регистрация: 03.12.2014
Сообщений: 29
12.02.2017, 15:45  [ТС] 4
Цитата Сообщение от Usaga Посмотреть сообщение
Valeov, по-моему, данный принцип так же оговаривает ожидания вызывающего кода в отношении вызываемого. Если вызывающий код допускает, что метод cut() сделает ничего (или ему просто пофигу на результат), а сам метод таки связан с резанием, то принцип подстановки Лисков не нарушен.
Ну в данном случае, том что реализовано кодом, вызывающий базовый класс код ждет что будет какая то порезка.
Я думаю, может от абстрактного класса лучше тогда наследовать.
AbstractKnife c его методом cut()
А от него уже будут наследоваться конкретные классы, Цельный Нож, Складной Нож.

Или может вообще вводить новый класс РежущееПоведение, которому классы ножей будут делегировать операцию порезки...
Смотрел паттерны, ниче похожего не нашел, хотя вроде ситуация из распространеных
0
Эксперт .NET
9443 / 6815 / 1094
Регистрация: 21.01.2016
Сообщений: 25,905
12.02.2017, 15:49 5
Valeov, в данном случае самый разумный выход - не плодть 100500 уровней абстракции непонятно для чего, а изменить вызывающий код, чтобы он допускал невыполнение методом cut() своей задачи. Помни: SOLID - рекомендации для поддержания порядка в коде, а не самоцель.
0
Модератор
2843 / 2009 / 431
Регистрация: 26.03.2015
Сообщений: 7,723
12.02.2017, 16:06 6
Цитата Сообщение от Valeov Посмотреть сообщение
Ну в данном случае, том что реализовано кодом, вызывающий базовый класс код ждет что будет какая то порезка.
Я думаю, может от абстрактного класса лучше тогда наследовать.
AbstractKnife c его методом cut()
А от него уже будут наследоваться конкретные классы, Цельный Нож, Складной Нож.
Да.
Если методы cut() у целого и складного ножей принципиальные различия, то нельзя наследовать один от другого.

Цитата Сообщение от Valeov Посмотреть сообщение
Или может вообще вводить новый класс РежущееПоведение, которому классы ножей будут делегировать операцию порезки...
Нет.
Если сомневаетесь, нужно ли вводить новый уровень абстракции, то не вводите.
0
1 / 1 / 0
Регистрация: 03.12.2014
Сообщений: 29
13.02.2017, 17:23  [ТС] 7
Думаю все таки есть нарушение, вот нашел чем то похожий случай (Subtle Violation) , автор коммента объясняет что ИгрушечнуюМашинку нельзя делать наследником "Машины", т.к. от последнего ожидается что после поездки уменьшится кол-во оставшегося топлива.
1
Заблокирован
13.02.2017, 17:56 8
Цитата Сообщение от Valeov Посмотреть сообщение
автор коммента объясняет что ИгрушечнуюМашинку нельзя делать наследником "Машины", т.к. от последнего ожидается что после поездки уменьшится кол-во оставшегося топлива.
Это чушь. Игрушечную машинку нельзя делать наследницей настоящей просто потому что смысла в этом нет, однако же сам аргумент про топливо является маразмом. Тут подойдет пример с электрокаром. Электрокар не потребляет топливо, но потребляет энергию аккумулятора, соответственно, нет никаких причин не делать электрокар наследником автомобиля на этом основании, просто нужно строить обобщение таким образом, чтобы в надклассе не было конкретизации по топливу.
0
Эксперт .NET
9443 / 6815 / 1094
Регистрация: 21.01.2016
Сообщений: 25,905
13.02.2017, 18:40 9
asmquest, ну, про маразм - это ты сильно радикально высказался. Принцип подстановки Лисков затрагивает как "машинки" так и код, который с ними работает. Если вызывающему коду критично, чтобы топливо расходовалось (менялось состояние "машинки"), то принцип нарушен (если один из наследников этого не делает), если не критично, то всё пучком. Момент спорный, как мне кажется, и сильно зависит от ситуации.
0
Заблокирован
13.02.2017, 19:01 10
Цитата Сообщение от Usaga Посмотреть сообщение
сильно зависит от ситуации.
ясно что зависит, это о любом паттерне можно сказать, однако же автор того поста делает категоричный вывод.
0
Эксперт .NET
9443 / 6815 / 1094
Регистрация: 21.01.2016
Сообщений: 25,905
13.02.2017, 19:04 11
asmquest, ну так он уточнил, почему сделал такой вывод:

Цитата Сообщение от Valeov Посмотреть сообщение
т.к. от последнего ожидается что после поездки уменьшится кол-во оставшегося топлива.
Т.е. после вызова метода ожидается изменение состояния, чего не происходит в случае описанном в примере. ТС провёл прямую аналогию со своим режет-нережет. Оттуда и вывод.
0
1 / 1 / 0
Регистрация: 03.12.2014
Сообщений: 29
14.02.2017, 08:29  [ТС] 12
Цитата Сообщение от asmquest Посмотреть сообщение
Тут подойдет пример с электрокаром. Электрокар не потребляет топливо, но потребляет энергию аккумулятора, соответственно, нет никаких причин не делать электрокар наследником автомобиля на этом основании, просто нужно строить обобщение таким образом, чтобы в надклассе не было конкретизации по топливу.
Речь то о том что например есть конкретный класс Машина, с реализованным функционалом для двигателя внутреннего сгорания.
Потом раз, потребовался Электрокар, взял отнаследовал его от Машина, переопределил что надо, и думаешь что окей, а тут окажется нарушен LSP.
Эта ситуация кореллирует с моим вопросом по ножам.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.02.2017, 08:29

SOLID принципы
всего 5 принципов: 1) srp - класс должен описывать только те характеристики, которые на объект из...

Принцип DIP из SOLID
Правильно ли я понял принцип DIP из SOLID? Если класс A имеет зависимость от класса B, то при...

Пятый принцип SOLID
Здравствуйте. Формулировка пятого принципа гласит о том, что модули верхнего уровня не должны...

Solid Converter PDF v4
братва,скачал Solid Converter PDF v4,но не могу найти в нем таблетку,если кто знает скинте где...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru