Должен ли я переименовывать переменные, которые уже являются константами в моей собственной библиотеке?

Я пишу обертку высокого уровня вокруг Python socket.socket . В частности, я хочу сделать это для сокетов TCP IPv4 (хотя было бы полезно иметь возможность расширять библиотеку позже с другими семействами /типами). Как вы знаете, модуль сокетов определяет их как socket.AF_INET и socket.SOCK_STREAM . Это хорошая идея «скопировать» эти константы и сделать их постоянными атрибутами класса, то есть:

import socket


class IPv4TCPSocket(socket):
    FAMILY = socket.AF_INET
    TYPE = socket.SOCK_STREAM

    def __init__(self):
        ...

Или я должен обращаться к ним напрямую? Я получаю это может показаться странным вопросом, поскольку они уже являются константами в модуле socket, но ссылаясь на них на <libname>.socket.AF_INET может быть немного неудобно. Любые мысли об этом?


В качестве альтернативы я просто оставляю атрибуты класса и инициализирую так:

super().__init__(family=socket.AF_INET, type=socket.SOCK_STREAM)

Это полностью исключает ссылку на семейство сокетов и тип, который, я думаю, не является проблемой, за исключением случаев, когда кому-то еще нужно создать собственный сокет (или получить один из IPv4TCPSocket):

from <name> import IPv4TCPSocket as sock


print("Creating a new socket with family {} and type {}!".format(sock.FAMILY, sock.TYPE))

В отличие от

import <libname>

print("Creating a new socket with family {} and type {}!".format(<libname>.socket.AF_INET, <libname>.socket.SOCK_STREAM))

Это немного больше работы и не похоже на интуитивный публичный интерфейс для меня. И эй, я могу просто превратить это в проблему, большую проблему, чем на самом деле, но я делаю это много:)


Второе редактирование: новые мысли по этому вопросу. После прочтения комментария Джеймса я узнал (опять же, duh!), Что socket.socket.type и socket.socket.family существуют, которые возвращают тип и семейство экземпляров сокета соответственно. Итак, поскольку я хочу отделить поведение класса от типа & семейный базис, я не могу подклассы socket вообще. Однако вопрос остается тем же, поскольку каждый из этих экземпляров обертки должен иметь собственный атрибут _socket.


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


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

3 голоса | спросил Daniel 5 TueEurope/Moscow2017-12-05T22:31:19+03:00Europe/Moscow12bEurope/MoscowTue, 05 Dec 2017 22:31:19 +0300 2017, 22:31:19

1 ответ


3

Общий ответ на вопрос:

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

Первая и самая важная причина в том, что если вы «спрятали» то, что используете, ваша библиотека не замужем за этой зависимостью, пока смерть не разорвет их. Если в один прекрасный день вы нашли другую библиотеку, которая лучше всего служит вашим целям (или вы решите реализовать эту функцию самостоятельно), вы можете сделать обмен, не обращая внимания на ваши пользователи.

И еще одна причина заключается в том, что в большинстве случаев ваши пользователи ищут абстрагирование /упрощение по сравнению с необработанными низкоуровневыми библиотеками. Они хотят «не заставляйте меня думать» о решениях с минималистичными, элегантными API-интерфейсами, которые позволят им быстро сделать дерьмо и не тратить лишние мозговые циклы. Если вы раскрываете или просачиваете внутренние данные в свой API, вы просто заставляете ваших пользователей знать ненужные данные и сделать их жизнь труднее без уважительной причины.

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

Конкретный ответ на вашу проблему:

Если вы разрабатываете класс под названием IPv4TCPSocket, не имеет смысла делать family или type каким-либо образом видимым или настраиваемым, поскольку сокет TCP в значительной степени определяет данное семейство и тип. Это позволит просто запутать пользователей и сделать абстракцию абсурдной. Самый чистый подход - хранить основной экземпляр сокета в частных членах вашего класса и выставлять нужные члены.

ответил bgusach 12 TueEurope/Moscow2017-12-12T01:05:05+03:00Europe/Moscow12bEurope/MoscowTue, 12 Dec 2017 01:05:05 +0300 2017, 01:05:05

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132