Skip to content

Mixins considered harmful

dependencies are compared with mixins often, since both solutions are ways to maximize code reuse. We already discussed this in the why chapter. But let's return to it again:

Note

Inheritance always breaks encapsulation.

Mixin class depends on attributes set in other classes.

Consider this code snippet:

>>> class RetrieveModelMixin:
...     """
...     Retrieve a model instance.
...     """
...
...     def retrieve(self, request, *args, **kwargs):
...         instance = self.get_object()
...         serializer = self.get_serializer(instance)
...         return Response(serializer.data)

Where were get_object and get_serializer defined? We have no idea. We believe the code below is way better in the sense of understandability:

>>> class RetrieveModel:
...     """
...     Retrieve a model instance.
...     """
...     def __init__(self, get_object, get_serializer):
...         self.get_object = get_object
...         self.get_serializer = get_serializer
...
...     def retrieve(self, request, *args, **kwargs):
...         instance = self.get_object()
...         serializer = self.get_serializer(instance)
...         return Response(serializer.data)

— ⭐ —