Много похожих методов или один метод, который принимает много параметров?

Мне трудно выбрать между вариантами того, как написать этот клиент ниже:

import requests
  1. Метод зависит:
class Client:

    def request_endpoint_1(self, **params):
        return requests.get('url_1', params)

    def request_endpoint_2(self, **params):
        return requests.get('url_2', params)
    
    def request_endpoint_3(self, **params):
        return requests.get('url_3', params)
    .
    .
    .
  1. Зависит от аргумента:
from enum import Enum


class Endpoint(Enum):
    endpoint_1 = 'url_1'
    endpoint_2 = 'url_2'
    endpoint_3 = 'url_3'
    .
    .
    .


class Client:

    def request(self, endpoint: Endpoint, **params):
        return requests.get(endpoint.value, params)

Учитывая, что количество конечных точек очень велико (100+), второй вариант кажется лучшим выбором, поскольку он повторяется значительно меньше, и я предполагаю, что выделение памяти для перечислений также меньше, чем такое же количество методов экземпляра в 1-й вариант.

Но если я выберу вариант 1, это сделает код более удобным для IDE и более простым для написания кода с использованием Client методов. При варианте 2 пользователь также должен импортировать класс Endpoint(Enum), который будет находиться в другом модуле, чем Client.

Вопрос в том, какой из них я должен использовать и почему? Я также хочу узнать, есть ли между ними значительная разница в эффективности памяти.

Сделайте оба. Первый вариант — общедоступный класс с явными и задокументированными параметрами. Второй вариант — это базовый класс, который обрабатывает фактическое выполнение и ведение журнала. Перечисление может быть ненужным, но может помочь в регистрации. Различия во время выполнения маловероятны, и в любом случае запрос будет ничтожным.

Kenny Ostrom 30.03.2023 04:31

@KennyOstrom Каждый метод на самом деле имеет еще несколько параметров в дополнение к URL-адресу. В этом случае каждое перечисление будет кортежем, например: (url, method, auth_type, ...)

UpTheIrons 30.03.2023 04:32

Гораздо проще поместить именованные параметры в метод со строкой документации и подсказками типа.

Kenny Ostrom 30.03.2023 04:35

@KennyOstrom Итак, определение сотен методов с большим количеством повторений def...return requests.get(... **params) считается хорошей практикой?

UpTheIrons 30.03.2023 04:38

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

Kenny Ostrom 30.03.2023 04:41
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
5
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

Итак, чтобы ответить на заголовок вопроса «Много похожих методов против одного метода, который принимает много параметров?», Я бы сказал, что лучший подход - написать «много непохожих методов».

Например (используя какой-то воображаемый API хранилища):

class Client:
    def __init__(self, auth_key: str):
        self.common_params = {'auth_key': auth_key}

    def list_directory(self, path: str, recursive: bool = False) -> list[str]:
        return [
            file['name']
            for file in requests.get('url_1', params = {
                'path': path,
                'recursive': 'yes' if recursive else 'no',
                **self.common_params
            }).json()['files']
        ]

    def copy_file(self, from_path: str, to_path: str) -> None:
        requests.get('url_2', params = {
            'from_path': from_path,
            'to_path': to_path,
            **self.common_params
        })

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

UpTheIrons 30.03.2023 07:35

Считаете ли вы, что Python выделял бы слишком много памяти, чтобы быть неэффективным, если бы было около 500 методов, таких как два в вашем ответе? Я, вероятно, все равно буду придерживаться методов, но это было моей главной заботой.

UpTheIrons 30.03.2023 07:35

Объем памяти, занимаемый скомпилированными байт-кодами, обычно ничтожно мал по сравнению с реальными пользовательскими данными, а 500 методов — это не так уж и много, если они служат совершенно разным целям. Однако документация вашего клиентского API должна разбивать 500 методов по категориям для облегчения навигации.

blhsing 30.03.2023 07:40

Не стесняйтесь обновить свой вопрос, добавив более содержательный пример API, демонстрирующий природу 500 методов, с которыми вы имеете дело. На данный момент они выглядят слишком общими, чтобы сказать, требуют ли они другого шаблона программирования.

blhsing 30.03.2023 07:43

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

UpTheIrons 30.03.2023 08:44

Другие вопросы по теме