2016-02-09 3 views
0

Я пишу серверное приложение, функция которого вызывается через RPC. Приложение имеет объекты, которые могут взаимодействовать друг с другом.Как объявить, какие методы могут быть применены к объектам

Предположим следующего упрощенного примера:

  • Человек может проверить и исправить, и может быть проверен;
  • Автомобиль может тормозить и может быть проверен и исправлен.

Непосредственная реализация ¹ (RPC вне области видимости):

class Car(object): 
    def __init__(self, broken=False): 
     self.name = 'car' 
     self.broken = broken 

    def breaks(self): 
     self.broken = True 
     print 'Car broke' 

    def inspected(self, by): 
     if by.pro: 
      if self.broken: 
       print '{}: It\'s a broken car'.format(by.name) 
      else: 
       print '{}: It\'s a working car'.format(by.name) 
     else: 
      print '{}: It\'s a car'.format(by.name) 

    def fixed(self, by): 
     if not self.broken: 
      print 'Car is not broken' 
     else: 
      self.broken = False 
      print by.name, 'fixed the car' 


class Person(object): 
    def __init__(self, name, pro=False): 
     self.name = name 
     self.pro = pro 

    def inspect(self, target): 
     target.inspected(by=self) 

    def fix(self, target): 
     target.fixed(by=self) 

    def inspected(self, by): 
     if self.pro: 
      print '{}: {} is a pro'.format(by.name, self.name) 
     else: 
      print '{}: {} is not a pro'.format(by.name, self.name) 

Создайте несколько объектов:

>>> car = Car() 
>>> john = Person('John', pro=True) 
>>> bob = Person('Bob', pro=False) 

Теперь пользователь может взаимодействовать с ними ²:

>>> car.breaks() 
'Car broke' 
>>> john.inspect(car) 
"John: It's a broken car" 
>>> john.fix(car) 
'John fixed the car' 
>>> bob.inspect(john) 
'Bob: John is a pro' 

Проблема здесь, если мы позвоним john.fix(bob), тогда мы получим AttributeError: 'Person' object has no attribute 'fixed'.

Итак, что такое хороший и/или «путинский» способ объявить/ограничить, какие методы могут быть применены к каким объектам?

До сих пор я придумал следующие идеи:

  1. Сделать раздутую базу (реферат) классом, который будет иметь заглушки для всех возможных методов и свойств. Недостатком здесь является то, что по мере роста проекта и добавления новых методов его следует обновлять отдельно; и у всех дочерних классов будет много несвязанных и неиспользуемых вещей. Кроме того, на самом деле проблема не решена.
  2. Оберните все звонки try...except. Не выглядит стабильным и «питоническим», и не решает проблему.
  3. Вручную укажите, какие классы поддерживаются методами. Не поддерживается, поскольку проект растет, и строго не указывает, какие атрибуты должен иметь целевой класс.
  4. Множественное наследование. Устраняет проблему с # 3, когда при создании нового класса FixAllRobot с методом fix мы можем забыть добавить атрибут pro, необходимый для проверок цели. Минусы: class Person(Inspecter, Fixer, ..., TwentyMoreOneFunctionHolder) не выглядит заслуживающим доверия и удобочитаемым. И нам все равно нужно проверить, можно ли использовать действие по назначению.
  5. Очень похоже на # 4, но наследуют также целевые классы. Минусы: Наследование ада: class Person(Inspecter, CanBeInspected, Fixer, ..., FortyMoreOneFunctionHolder). Плюсы: Похоже на решение.

Примечание:

  1. О инспектировать и осмотреть (и другие пары действий): Есть некоторые зависимые действия класса как для объекта и субъекта, который должен быть сделан, когда действие называется.

  2. Пока что все объекты того же класса хранятся в словаре классов со своим ключом id. Мета-класс отслеживает, какие классы были созданы. Обычно пользователь контролирует только один объект.Когда пользователь отправляет RPC-запрос (фактически json-rpc), который может выглядеть как {"jsonrpc": "2.0", "id": 77, "method": "inspect", "params": {"target": "car", "id": 1}}, target разрешен как целевой класс и id как идентификатор экземпляра. Некоторые необязательные параметры также могут быть переданы через params dict.

Sidenote: Я знаю систему сигнальных слотов QT и люблю ее, но я думаю, что это не так.

Sidenote2: Я застрял в Python 2.7

+0

Ваш вопрос не имеет большого смысла. Что может быть ** ограничение ** на самом деле делать иначе, чем возбуждать исключение? Python уже делает правильную вещь, поднимая 'AttributeError', поэтому нет проблем для решения. Все, что вам нужно сделать, это предоставить соответствующую документацию для ваших API. – ekhumoro

+0

Речь идет не о ограничении в использовании, а о проектировании его ядра, как будет очевидно, что нужно делать, чтобы правильно добавлять новые функции, например zope.interface. – mFoxRU

+0

Пример «проблемы», который вы дали, является, в частности, ограничением в использовании - то есть вызовом 'john.fix' с неправильным типом аргумента. – ekhumoro

ответ

1

я предлагаю идти с методом try...except. EAFP («Легче просить прощения, чем разрешение») соответствует https://docs.python.org/2/glossary.html#term-eafp, рассматриваемому как pythonic. Он также хорошо масштабируется, так как проект растет.

+0

Мое чувство красоты говорит мне, что обертывание каждого метода вызовом с помощью try ... за исключением не выглядит хорошо. И указание в документации, что каждый новый метод также должен делать это выглядит ужасно. – mFoxRU

Смежные вопросы