@zlodiak

Почему интерфейсы не избыточны?

В учебниках по ООП часто пишут, что программировать нужно не на уровне реализации, а на уровне интерфейсов. Я не понимаю причину этого, объясните пожалуйста.

Для примера приведу классический паттерн Observer. Он имеет абстрактные классы Observer и Observable с интерфейсами, которые обязаны реализовать наследники:

#!/usr/bin/env python3

from abc import ABCMeta, abstractmethod

class Observer(metaclass=ABCMeta):
    @abstractmethod
    def update(self, message):
        pass

class Observable(metaclass=ABCMeta):
    @abstractmethod
    def register(self, observer):
        pass

    @abstractmethod
    def notify_observers(self, message):
        pass

class Newspaper(Observable):
    def __init__(self):
        self.observers = []

    def register(self, observer):
        self.observers.append(observer)

    def notify_observers(self, message):
        for observer in self.observers:
            observer.update(message)

    def add_news(self, news):
        self.notify_observers(news)

class Citizen(Observer):
    def __init__(self, name):
        self.name = name

    def update(self, message):
        print('{} получил: {}'.format(self.name, message))

newspaper = Newspaper() 
newspaper.register(Citizen('Иван'))  
newspaper.register(Citizen('Василий')) 
newspaper.add_news('Сообщение')


Однако, код станет заметно проще, если отказаться от использования абстрактных классов(а значит и интерфейсов). Подскажите пожалуйста возможные сценарии развития представленного кода, в которых будет ощущаться неудобство от отсутствия метаклассов Observer и Observable
  • Вопрос задан
  • 315 просмотров
Решения вопроса 1
@LODIII
Python/SQL developer
Использовать ABC не обязательно. Есть множество литературы, например
Марк Саммерфильд. Python на практике... и другие есть примеры где патерн Наблюдатель
создан без такого наследования.
Особенно все что касаемо Питона 2.7.
Но пусь питона - постояное улучшение и именно для этого в Питон 3 было введено понятие из Java
abc, которое позволяет писать более грамотно,(ИМХО в данном случае если архитектор задаст определенные правила то можно быть уверенным что джуниор не сможет забыть написать требуемую реализацию.)
В данном PEP это как раз объяснено
https://www.python.org/dev/peps/pep-3119/
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@Andy_U
В приведенном коде все будет работать и без абстрактных классов. Но если в конце (перед newspaper.add_news('Сообщение')) добавить строчку newspaper.register('abc'), то лишь выполнение программы закончится с ошибкой. Если код сложнее представленного, ошибка может всплыть совсем не сразу. Тот же Pycharm данную ошибку никак не сможет обнаружить.

А вот если к коду добавить type hints:
from typing import List
from abc import ABC, abstractmethod


class Observer(ABC):
    @abstractmethod
    def update(self, message: str) -> None:
        pass


class Observable(ABC):
    @abstractmethod
    def register(self, observer: Observer) -> None:
        pass

    @abstractmethod
    def notify_observers(self, message: str) -> None:
        pass


class Newspaper(Observable):
    def __init__(self) -> None:
        self.observers: List[Observer] = []

    def register(self, observer: Observer) -> None:
        self.observers.append(observer)

    def notify_observers(self, message: str) -> None:
        for observer in self.observers:
            observer.update(message)

    def add_news(self, news: str) -> None:
        self.notify_observers(news)


class Citizen(Observer):
    def __init__(self, name: str) -> None:
        self.name = name

    def update(self, message: str) -> None:
        print('{} получил: {}'.format(self.name, message))


if __name__ == '__main__':

    newspaper = Newspaper()
    newspaper.register(Citizen('Иван'))
    newspaper.register(Citizen('Василий'))
    newspaper.register('abc')
    newspaper.add_news('Сообщение')

то при использовании Pycharm или mypy они сразу отругаются на ошибку типа:
(VENV~1) D:\My Documents\PycharmProjects\tst>mypy --strict tst105.py
tst105.py:49: error: Argument 1 to "register" of "Newspaper" has incompatible type "str"; expected "Observer"


Т.е., если пишете небольшие программы исключительно для себя в notepad'е - можно и без абстрактных классов и type hints. А вот во всех иных случаях - лучше действовать профессионально.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы