Изменения в производительности нарушают принцип замещения Лискова?

14

Скажи, что у меня есть:

interface Thing
{
    GetThing();
}

class FastThing : Thing 
{
    public int GetThing()
    {
        return 1;
    }
}

class SlowThing : Thing
{
    public int GetThing()
    {
        return GetThingFromDatabase();
    }
}

Это нарушение принципа подстановки Лискова?

ConditionRacer
источник
GetThingFromDatabase()не достаточно медленно, чтобы сделать это спорным. Factor4096BitPublicKey();return 1;сделало бы вещи немного интереснее.
Патрик
1
Если вы замените FastThingна SlowThing, LSP не применяется. Если вы добавите комментарий, в Thing::GetThingкотором написано «Очень быстро», вопрос можно обсудить.
Головоногий

Ответы:

14

Это действительно зависит. Некоторые интерфейсы имеют, например, ограничения сложности (они, очевидно, не могут быть реализованы программно). Наиболее простой случай - «GetThing () дает int- то есть останавливает», и в этом случае ответом будет «Нет» - обе версии GetThing () останавливают и возвращают int.

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

DeadMG
источник
3
Производительность не является чем-то обязательным с помощью проверки типа. Это обещание разработчика / сопровождающего библиотеки.
dietbuddha
3
Я прямо так заявил в своем ответе?
DeadMG
1
Моя точка зрения заключалась в том, что как только вы включаете в критерии что-либо кроме ввода, вы больше не говорите о Лискове, так как это относится к типу. Хотя «практика» отказа от других объектов может быть хорошей, самому Лискову нечего сказать по этому поводу.
dietbuddha
7
Лисков утверждает, что для Производных он должен использоваться везде, где есть База. Это может быть неверно, если База гарантирует определенные характеристики или характеристики. Например, если производные блоки, могут быть потенциальные взаимоблокировки.
DeadMG
8

TL; DR: нет

Согласно «Поведенческому подтипу с использованием инвариантов и ограничений» (формализация принципа), он в первую очередь касается «безопасных» свойств типа объектов. Свойства, которые определяют заменяемость только в контексте информации о типе. Тип объекта ортогональн к его производительности. Поэтому разница в производительности не является нарушением принципа подстановки Лискова.

dietbuddha
источник
3
Я только кратко изучил этот документ, но уверены ли вы, что временные ограничения не могут быть сделаны формально доказуемыми? И даже если Лисков не имел в виду, что на словах, включая временные ограничения, можно рассматривать как хорошее расширение классического LSP, которое может иметь отношение к программированию в реальном мире.
Док Браун
@Doc Brown: полезно ли время для замены объекта или нет, ортогонально Лискову. Можно добавить это как отдельную заповедь, но она не может и никогда не будет частью Лискова. Это похоже на булево логическое уравнение и выражение! False можно заменить только True, если это достаточно быстро. Скорость не имеет ничего общего с математикой или логикой.
dietbuddha
Контрпример: этот код вызывается в EDT Java или в цикле событий Node. Радикально медленная производительность медленной версии приведет к полуразрушению программного обеспечения. Я думаю, что правильный ответ на этот вопрос «вероятно, нет, но есть исключения».
user949300
6

Какие гарантии дает интерфейс? Так как не GetThingдает никаких гарантий, тогда подтипы не должны уважать это.

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

Telastyn
источник
4

Производительность программного обеспечения не имеет ничего общего с принципом подстановки Лискова.

Принцип связан с заменой подтипов и поведенческим воздействием замены этого объекта только в терминах ООП.

Вход и выход getThing()остаются одинаковыми для обоих случаев, и как медленные, так и быстрые, вероятно, переводят объекты в одно и то же состояние.

Reactgular
источник
1

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

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

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

trptcolin
источник
2
насколько я могу судить, приведенный пример не является Java
gnat
0

Дядя Боб ответил на очень похожий вопрос, где он заявляет, что нарушение LSP требует 3 сторон:

Тип T, Подтип S и программа P, которая использует T, но получает экземпляр S.

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

Вы можете найти его ответ здесь . (Вам нужно прокрутить вниз и найти ответ от пользователя по имени Роберт Мартин)

TMC
источник
1
как это отвечает на заданный вопрос?
Комнат
@gnat Потому что вопрос, как он задан, является неполным. Требуется 3 стороны, чтобы определить нарушение LSP. Из которых он поставил только 2 партии.
TMc