Как объединить два класса Python, содержащие методы с одинаковыми сигнатурами? - PullRequest
2 голосов
/ 06 марта 2012

Я работаю над клиентской библиотекой REST и недавно начал работать над добавлением поддержки отправки пакетных сообщений.

Однако мне не нравится текущий дизайн.Это требует от вас поддерживать большие классы Client и RequestMessage с одинаковыми сигнатурами методов.

Я ищу способ объединения двух классов.

Методы исходного класса клиента содержали весь код, необходимый для подготовки и отправки запроса:

class Client(object):

   def __init__(self, config):
       self.request = Request(config, "application/json")

   def create_vertex(self, data):
       path = "vertices"
       params = remove_null_values(data)
       self.request.post(path, params)

Чтобы добавить поддержку для пакетных сообщений, я вытащил кишки кода внутри каждого метода Client и поместил его в отдельный класс RequestMessage, чтобы вы могли добавлять сообщения в пакет без отправки, пока вы не будете готовы:

class Client(object):

   def __init__(self, config):
       self.request = Request(config, "application/json")
       self.message = RequestMessage(config)

   def create_vertex(self, data):
       message = self.message.create_vertex(data)
       return self.request.send(message)

   # ...more REST client methods...

   def batch(self, messages):
       path = "batch" 
       params = messages
       return self.request.post(path, params)       

class RequestMessage(object):

   def __init__(self, config):
       self.config = config

   def create_vertex(self, data):
       path = "vertices"
       params = remove_null_values(data)
       return POST, path, params

  # ...more REST client methods...

Но мне не нравится дизайн, потому что теперь вам нужно поддерживать класс Client и RequestMessage - два больших класса с одинаковыми сигнатурами.

Вот как выглядит класс Batch:

class Batch(object):

   def __init__(self, client):
       self.client = client
       self.messages = []

   def add(self, message):
       self.messages.append(message)

   def send(self):
       return self.client.batch(self.messages)

Вот пример использования для создания вершины на сервере:

>>> client = Client(config)
>>> vertex = client.create_vertex({'name':'James'})

Вот пример использования для создания пакета вершин на сервере:

>>> message1 = client.message.create_vertex({'name':'James'})
>>> message2 = client.message.create_vertex({'name':'Julie'})
>>> batch = Batch(client)
>>> batch.add(message1)
>>> batch.add(message2)
>>> batch.send()

Пакетный режим используется реже, чем Client, поэтому я хочу сделать обычный интерфейс Client более простым в использовании.

Вот одна из идей, но я не совсем уверен, как этого добиться.накануне или если что-то еще будет лучше:

   >>> vertex = client.create_vertex(data)
   >>> message = client.create_vertex(data).message()

Ответы [ 2 ]

1 голос
/ 06 марта 2012

Я бы согласился с @Karl с некоторыми модификациями

client.create_vertex({'name':'James'}) # single
client.create_vertex({'name':'James'}, {'name':'Julie'}) # batch

batch = []
batch.append({'name':'James'})
batch.append({'name':'Julie'})
client.create_vertex(*batch)

Таким образом, вам не нужно проверять тип ввода. Легче писать, проще в использовании.

1 голос
/ 06 марта 2012

Мои личные предпочтения - это API:

client.create_vertex({'name':'James'}) # single
client.create_vertex([{'name':'James'}, {'name':'Julie'}]) # batch

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

batch = []
batch.append({'name':'James'})
batch.append({'name':'Julie'})
client.create_vertex(batch)
...