This has really nothing to do with MVC but I came across the issue and also found a related question in that context. Unfortunately the related question fell short of describing where the LSP violation occurs in its original example and thus did not produce a satisfactory answer.
Suppose we have an MVC (or any other) framework/library providing a couple of base classes that work together as aggregates, here
class Model: def __init__(self, data): self.data = data class View: def set_model(self, model: Model): self._model = model def draw(self): self._draw_data(model.data)
(incomplete code obviously, but you get the idea)
Let's say I want the views in my application to always show a title. So I'll derive all my model classes from
class MyModel(Model): def __init__(self, data): self.data self.title = ''
So far so good, no LSPs violated yet. I'll also create a new view base class which shall require its model to be of type
MyModel so that it can draw a title.
class MyView(View): def set_model(self, model: MyModel): super().set_model(model) def draw(self): super().draw() self._draw_title(model.title)
Now I have a covariant argument on
set_model and thus violated LSP. What would be a better way to design this? Or does Liskov not apply here? If so, why?
I could obviously check the type of
model in the draw method but in a more complex real-world example I may end up adding lots of type checking code which doesn't feel right either.