Почему МОК / DI, не распространенный в Python?

В Java МОК / DI является очень обычной практикой, которая экстенсивно используется в веб-приложениях, почти всех доступных платформах и Java EE. С другой стороны, существует также много больших веб-приложений Python, но около Zope (то, которое я услышал, должно быть действительно ужасным для кодирования) МОК, кажется, не очень распространен в мире Python. (Назовите некоторые примеры, если Вы думаете, что я неправ).

Существует, конечно, несколько клонов популярного Java платформы МОК, доступные для Python, springpython, например. Но ни один из них, кажется, не привыкает практически. По крайней мере, я никогда не имею stumpled на Django или sqlalchemy + основанное веб-приложение, которое использует что-то как этот.

По-моему, МОК имеет разумные преимущества и помог бы заменить django-default-user-model, например, но обширное использование интерфейсных классов и МОК в Python выглядит немного нечетным и не» pythonic «. Но возможно у кого-то есть лучшее объяснение, почему МОК широко не используется в Python.

296
задан alexandrul 17 April 2011 в 19:36
поделиться

6 ответов

На самом деле я не думаю, что DI / IoC что необычно для Python. То, что является необычным, это структуры / контейнеры DI / IoC .

Подумайте: что делает контейнер DI? Это позволяет вам

  1. соединять вместе независимые компоненты в полное приложение ...
  2. ... во время выполнения.

У нас есть названия для «соединения вместе» и «во время выполнения»:

  1. scripting
  2. dynamic

Итак, контейнер DI - это не что иное, как интерпретатор для динамического языка сценариев. На самом деле, позвольте мне перефразировать это: типичный контейнер Java / .NET DI - это не что иное, как дрянной интерпретатор действительно плохого языка динамических сценариев с уродливым, иногда основанным на XML, синтаксисом.

Когда вы программируете на Python, зачем вам использовать уродливый, плохой язык сценариев, когда в вашем распоряжении прекрасный, блестящий язык сценариев? На самом деле, это более общий вопрос: когда вы программируете практически на любом языке, зачем вам использовать уродливый, плохой язык сценариев, когда в вашем распоряжении Jython и IronPython?

Итак, резюмируем: практика DI / IoC так же важна в Python, как и в Java, по точно таким же причинам. Однако реализация DI / IoC встроена в язык и часто настолько легковесна, что полностью исчезает.

(Небольшое отступление для аналогии: в сборке вызов подпрограммы - довольно серьезное дело - вам нужно сохранить локальные переменные и регистры в памяти, сохранить где-нибудь свой адрес возврата, изменить указатель инструкции на подпрограмму, которую вы вызываются, сделайте так, чтобы он каким-то образом вернулся в вашу подпрограмму, когда она будет завершена, поместите аргументы куда-нибудь, где вызываемый может их найти, и т. д. IOW: в сборке «вызов подпрограммы» является шаблоном проектирования, а до этого были такие языки, как Fortran, в которые были встроены вызовы подпрограмм, люди создавали свои собственные «структуры подпрограмм». Можно ли сказать, что вызовы подпрограмм «необычны» в Python только потому, что вы не используете каркасы подпрограмм?)

BTW: в качестве примера того, как выглядит доведение DI до логического завершения, взгляните на Гилада Браха язык программирования новояза и его работы по этой теме:

190
ответ дан 23 November 2019 в 01:34
поделиться

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

Это также симптом статически типизированного языка. Когда единственным инструментом, который у вас есть для выражения абстракции, является наследование, то это практически то, что вы используете повсеместно. При этом C++ довольно похож, но он никогда не был так увлечен построителями и интерфейсами, как разработчики Java. Легко увлечься мечтой о гибкости и расширяемости, но ценой написания слишком большого количества универсального кода с малой реальной пользой. Я думаю, это культурная особенность.

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

-3
ответ дан 23 November 2019 в 01:34
поделиться

Я не использовал Python несколько лет, но я бы сказал, что это больше связано с тем, что это язык с динамической типизацией, чем что-либо еще. В качестве простого примера на Java, если я хочу проверить, что что-то написано в соответствии со стандартом, я мог бы использовать DI и передать любой PrintStream, чтобы захватить записываемый текст и проверить его. Однако, когда я работаю в Ruby, я могу динамически заменить метод put в STDOUT, чтобы выполнить проверку, полностью исключив DI из поля зрения. Если единственная причина, по которой я создаю абстракцию, - это проверить класс, который ее использует (подумайте об операциях файловой системы или часах в Java), тогда DI / IoC создает ненужную сложность в решении.

12
ответ дан 23 November 2019 в 01:34
поделиться

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

Разница в том, что Python имеет первоклассные типы. Типы данных, включая классы, сами по себе являются объектами. Если вы хотите, чтобы что-то использовало определенный класс, просто назовите класс. Например:

if config_dbms_name == 'postgresql':
    import psycopg
    self.database_interface = psycopg
elif config_dbms_name == 'mysql':
    ...

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

my_db_connection = self.database_interface()
# Do stuff with database.

Вместо стандартных функций фабрики, которые нужны Java и C ++, Python делает это с помощью одной или двух строк обычного кода. В этом сильная сторона функционального программирования по сравнению с императивным.

34
ответ дан 23 November 2019 в 01:34
поделиться

Отчасти это способ работы модульной системы в Python. Вы можете получить своего рода «синглтон» бесплатно, просто импортировав его из модуля. Определите фактический экземпляр объекта в модуле, а затем любой клиентский код может импортировать его и фактически получить рабочий, полностью сконструированный / заполненный объект.

В этом отличие от Java, где вы не импортируете фактические экземпляры объектов. Это означает, что вам всегда нужно создавать их экземпляры самостоятельно (или использовать какой-то подход в стиле IoC / DI). Вы можете уменьшить проблемы, связанные с созданием экземпляров всего самостоятельно, имея статические фабричные методы (или фактические фабричные классы), но тогда вы по-прежнему будете нести накладные расходы ресурсов, фактически создавая каждый раз новые.

46
ответ дан 23 November 2019 в 01:34
поделиться

На самом деле, довольно легко писать достаточно чистый и компактный код с DI (интересно, будет ли он/останется питоническим тогда, но в любом случае :) ), например, я предпочитаю такой способ кодирования:

def polite(name_str):
    return "dear " + name_str

def rude(name_str):
    return name_str + ", you, moron"

def greet(name_str, call=polite):
    print "Hello, " + call(name_str) + "!"

_

>>greet("Peter")
Hello, dear Peter!
>>greet("Jack", rude)
Hello, Jack, you, moron!

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

P.S. Я также разместил более крупный пример этого наивного подхода на Динамическая оценка простой булевой логики в Python.

7
ответ дан 23 November 2019 в 01:34
поделиться
Другие вопросы по тегам:

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