Лучшая практика для переноса стороннего сервиса в библиотеку

#ruby-on-rails #ruby #api #design-patterns

#ruby-on-rails #ruby #API #шаблоны проектирования

Вопрос:

Я заинтересован в написании библиотеки для стороннего API, который я использую, и мне нужен совет. В среднем использование библиотеки будет включать несколько вызовов api в одном запросе. Например, один вызов api для захвата пользователя из стороннего сервиса, а затем другой вызов для использования этого пользователя для захвата его / ее фотографий. Каждый вызов API получит свою собственную оболочку библиотечного метода с дополнительной логикой для обработки ошибок / тайм-аутов, но мой самый большой вопрос заключается в том, должна ли библиотека создаваться как синглтон, содержащий состояние, или просто как серия методов класса.

Например:

 user_id = ThirdParty.get_user("abc@gmail.com")
photos = ThirdParty.get_photos(user_id)
  

или

 thirdpartyservice = ThirdPartyService.new("abc@gmail.com")
photos = thirdpartyservice.get_photos
  

Это не обязательно должен быть точный дизайн библиотеки, но я просто запутался в плюсах / минусах каждого подхода. Любая помощь была бы замечательной!

Кстати, я использую ruby!

Комментарии:

1. Что касается вопроса, связанного с созданием библиотеки в виде синглтона, хорошо бы сделать ее статическим классом со статическими методами, потому что я понимаю, что состояние библиотечного класса не обязательно поддерживать.

Ответ №1:

Я бы хотел, чтобы библиотека содержала состояние, поскольку это снижает сложность кода на стороне пользователя (и это то, что API должен делать, повышать простоту). При таком подходе пользователю не нужно отслеживать этот user_id, поскольку библиотека сохраняет его состояние.

Если пользователю действительно нужен их user_id (или любые другие данные, которые хранит библиотека), вы можете просто создать attr_reader в своей библиотеке, чтобы предоставить эти данные.

Чтобы добавить гибкость для метода get_photos, вы можете сделать что-то вроде:

 class ThirdPartyService

  def get_photos(user_id=@id_stored_in_library)
    # do work
  end

end
  

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

Ответ №2:

Вам нужно состояние (хост и т.д.) И поведение, основанное на этом состоянии, Поэтому вы должны использовать объекты, а не один одноэлементный объект.

Как уже упоминалось, вы не должны называть методы как get_photos , просто photos .

Комментарии:

1. Я согласен со стандартами именования. С точки зрения хоста и т.д., Вся эта информация постоянна. Информация о хосте и токене oauth одинакова для каждого вызова. Вы все еще думаете, что мне не следует использовать singleton?

Ответ №3:

Я считаю, что наилучшей практикой является использование provider и services для возможности не привязываться к определенному поставщику услуг. Вместо простого переноса библиотеки вы можете захотеть немного абстрагировать ее и по умолчанию разрешить использовать только одного поставщика услуг.

Хотя наследование на самом деле не требуется в языке с динамической типизацией, таком как Ruby, это может помочь конкретизировать «почему».

 class MailProvider 

  def initialize(args); raise "Not Implemented"; end

  def send_mail(args); raise "Not Implemented"; end

end

class SendGridService < MailProvider

  def initialize(args)
    # Use args here
  end

  def send_mail(args)
    # Use SendGrid's API or Gem here
  end

end
  

Тогда в вашем коде может быть что-то вроде этого:

 config.mail_provider = SendGridService.new({
  username: ENV['SENDGRID_USERNAME'],
  password: ENV['SENDGRID_PASSWORD']
})

config.mail_provider.send_mail({ subject: 'woot', message: 'Look ma, I did it!' })
  

Затем, шесть месяцев спустя, когда вашим пользователям понравится ваш Gem / library, но они захотят поддержки MailChimp, вы можете просто создать второй сервис «MailChimpService» и разрешить своим клиентам использовать нового поставщика.

Ответ №4:

Вместо методов get_ set_ будет лучше использовать геттеры и установщики. Это стандарт ruby (не уверен, но методы get_ и set_ я видел только один раз в коде ruby).

Если вам не нужно сохранять некоторое состояние между запросами, сделайте его статичным. Но это зависит от многих факторов. Можете ли вы сказать нам, какой API вам нужно обернуть?