python пример определение - Почему IoC / DI не распространен в Python?




7 Answers

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

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

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

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

  1. скриптовый
  2. динамический

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

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

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

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

Кстати: на примере того, как это похоже на то, чтобы привести к логическому завершению DI, взгляните на язык программирования GPRS Gilad Bracha и его статьи на эту тему:

простыми словами

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

Есть, конечно, несколько клонов популярных Java IoC framework, доступных для Python, например springpython . Но никто из них, похоже, практически не используется. По крайней мере, я никогда не замалчивал Django или sqlalchemy + <insert your favorite wsgi toolkit here> основе веб-приложения, которое использует что-то вроде этого.

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




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 делает это с одной или двумя строками обычного кода. Это сила функционального и императивного программирования.




IoC / DI - концепция дизайна, но, к сожалению, она часто используется как концепция, применимая к определенным языкам (или системам ввода). Я бы хотел, чтобы контейнеры для инъекций зависимостей стали намного более популярными в Python. Есть Spring, но это супер-каркас и, кажется, прямой порт концепций Java без особого внимания к «Пути Python».

Учитывая аннотации в Python 3, я решил получить трещину в полнофункциональном, но простом контейнере для инъекций: https://github.com/zsims/dic . Он основан на некоторых концепциях из контейнера для инъекций зависимостей .NET (который ИМО является фантастическим, если вы когда-либо играете в этом пространстве), но мутировал с концепциями Python.




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

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 по умолчанию тоже хватает.

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




Похоже, что люди действительно не получают то, что влечет за собой зависание и инверсия средств управления.

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

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

Для чего нужна библиотека DI, если вы можете создать экземпляр объекта внутри пакета и импортировать его, чтобы вставить его самостоятельно? Выбранный ответ прав, так как у java нет процедурных разделов (код вне классов), все, что входит в скучную конфигурацию xml, поэтому необходимо, чтобы класс создавал экземпляры и вводил зависимости от ленивой загрузки, чтобы вы не сдували ваша производительность, а на python вы просто кодируете инъекции на разделе «процедурные» (код вне классов) вашего кода




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

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

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




В отличие от сильной типизированной природы в Java. Поведение на языке утки Python позволяет легко передавать объекты.

Разработчики Java сосредоточены на построении класса strcuture и отношениях между объектами, сохраняя при этом все гибкость. IoC чрезвычайно важна для достижения этого.

Разработчики Python сосредоточены на выполнении работы. Они просто подключают классы, когда им это нужно. Им даже не нужно беспокоиться о типе класса. До тех пор, пока он может взломать, это утка! Эта природа не оставляет места для IoC.




Related