Рубрики
Без рубрики

Masonite Python Framework Series Series: Часть 1 – Понимание автоматического разрешения впрыска зависимости

Веб-каркас Masonite Python – это новый современный и разработчик, ориентированная на веб-каркас для Python. Теги с Python, программированием, рамками, масонитом.

Masonite Python Framework – это более современный подход к каркасам Python, чем в настоящее время на рынке. Смелое утверждение Но как только вы начнете использовать Masonite, вы будете поражены тем, насколько мощно может быть просто, используя несколько простых дизайнерских решений, которые другие рамки Python не имеют вроде контейнера IOC IOC зависимостей, образец медиатора (или менеджера). Многие из структуры, чтобы сохранить ее жидкость и расширяемое и многое другое проектные решения.

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

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

В этой первой части ряда я пойду в глубину, как масонит обрабатывает то, что он называет «Автоматическая инъекция зависимости»

Если вам пользуются этой статьей и наслаждайтесь написанием приложений с Masonite, рассмотрите возможность присоединиться к провисанию канала: http://slack.masoniteproject.com.

Что это?

Таким образом, впрыск зависимости – это слово $ 10 для определения 1 доллара. Проще говоря, это просто означает, что мы проходим что-то в объект, который ему нужно.

Возьмите этот простой пример:

from app import Model

def get_user_id(self, model):
    return model.find(1).id

user = get_user_id(Model)

На этом самым основным примере – модель является зависимостью для этой функции, и мы только что выполняли инъекцию зависимости. Мы «вводили» (или переданные) класс в этот объект функции.

Шаг вперед

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

ЗАМЕТКА: Это было бы плохим способом реализовать это, но просто следовать на данный момент:) Это только основы понимания того, как это работает.

from static_assets import AmazonUpload

container = {'upload': AmazonUpload}

def upload_image(self, upload):
    return upload.store('some-file.png')

Так что заметите здесь, что нам удобно иметь параметр под названием Загрузить и ключ словаря под названием Загрузить Отказ Это самая базовая основание «Авторазрешение» впрыска зависимости.

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

Если нам нужно изменить функциональность, мы просто поменяем класс в контейнере.

Еще один шаг вперед

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

Идея контейнера для казонита является «свободно паре» ваше приложение (обычно конкретные реализации) к вашим особенностям.

Используя upload_image Функция выше, что бы произошло, если бы босс пришел к вам и сказал: «Эй! Нам нужно начать загружать все в файловую систему, Amazon нашла слишком дорого для нашей компании ».. Тогда что вы делаете? Вы, вероятно, пройдете через ваш код и посмотрите что-то вроде этого:

from static_assets import AmazonUpload

def upload_image(self):
    return AmazonUpload.store('some-file.png')

def rename_image(self):
    return AmazonUpload.rename('some-file.png', 'another-file.png')

def delete_image(self):
    return AmazonUpload.delete('some-file.png')

def move_image(self):
    return AmazonUpload.move('some-file.png', 'another-location.png')

def copy_image(self):
    return AmazonUpload.copy('some-file.png', 'another-file.png')

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

Давайте возьмем еще один взгляд, но давайте лямбери наденьте наш контейнер, чтобы имя параметра снова совпадает с ключом словаря:

from static_assets import AmazonUpload

container = {'upload': AmazonUpload}

def upload_image(self, upload):
    return upload.store('some-file.png')

def rename_image(self, upload):
    return upload.rename('some-file.png', 'another-file.png')

def delete_image(self, upload):
    return upload.delete('some-file.png')

def move_image(self, upload):
    return upload.move('some-file.png', 'another-location.png')

def copy_image(self, upload):
    return upload.copy('some-file.png', 'another-file.png')

Автоматическая часть

Итак, теперь, когда вы понимаете концепцию «этот параметр, имеет то же имя, что и клавиша словаря», мы можем принять еще раз, еще один шаг дальше.

Замена фактической функциональности того, как масонит обрабатывает впрыск зависимости и использование псевдокода, автоматическая часть может выглядеть что-то вроде:

ЗАМЕТКА: Это псевдо код и не работает Python Code.

class Container

    providers = {'upload', AmazonUpload}

    def resolve(self, object_to_resolve):
        build_parameter_list = []

        # Get all of the objects parameters
        paramaters = inspect(object_to_resolve).parameters
        # returns ['upload']

        for paramater in paramaters:
            if paramater in self.providers:
                build_parameter_list.append(parameter)

        return object_to_resolve(*build_parameter_list)

Это действительно это. Чтобы объяснить его в человеческом терминам, мы просто используем проверку Python, чтобы получить список всех параметров. Например upload_image Функция выше даст нам «Загрузить» Потому что это имя параметра.

Автоматическая инъекция зависимости

OK! Таким образом, мы добрались до хороших вещей. Давайте начнем автоматическое разрешение наших зависимостей! Давайте возьмем загрузить изображение Пример выше:

from container import Container

def upload_image(self, upload):
    return upload.store('some-file.png')

uploaded_image = Container().resolve(upload_image)
# Looks into the container for the 'upload' key and injects it into the class.

Мы полностью удалили бетонную реализацию для загрузки_Image. Сейчас полностью «обслуживание агностики. «Неважно, если это Amazonupload Класс или Azureupload Класс и зависимость только в 1 месте. Теперь мы можем поменять функциональность на протяжении всего приложения по желанию.

Конкретный казонит

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

Masonite использует гораздо более продвинутый способ найти объекты для разрешения.

В Masonite мы используем эту функциональность, как это:

class WelcomeController:

    def show(self, Request):
        Request.user().id

«Запрос» – ключ в контейнере. Это слишком просто, чтобы давайте принять его, еще раз, еще один шаг вперед и показать, как масонитные обрабатывают функциональные аннотации.

Функциональные аннотации Python

Аннотации Python всегда были своего рода причудливыми. Это в основном комментарий в соответствии с параметром. Кажется странным. Когда они добавили это в Python, я не уверен, что это должно служить цели вообще в ядре Python. На самом деле это говорит об этом в Пепе:

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

Итак, какой масонит был в том, что в дополнение к зацикливанию через список параметров и разрешаю зависимости, мы также проходим сквозь аннотации и их тоже разрешаем. Вместо того, чтобы аннотировать нормально, как это:

def upload_image(upload: "pass in the upload class"):
    pass

Мы можем сделать его шаг вперед и пройти во всем классе:

from static_files import AmazonUpload

def upload_image(upload: AmazonUpload):
    pass

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

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

from masonite.view import View
from masonite.request import Request

class WelcomeController:
    ''' Controller For Welcoming The User '''

    def show(self, view: View, request: Request):
        ''' Show Welcome Template '''
        return view.render('welcome', {'request': request})

Подклассы (Advanced)

Если вы все поняли выше, мы сможем получить немного более продвинутым

Помимо получения класса, мы также можем получить подкласс класса, который является еще более мощным. Контейнер – это способ сохранить свое приложение свободно связано, но если мы пойдем с аннотациями, мы не можем поменять классы из контейнера по желанию. Сейчас мы сейчас «тесно» в сочетании с реализацией «бетона». Другими словами, мы можем использовать только 1 класс.

Возьми это, например:

from masonite.drivers import UploadS3Driver

class UploadController:
    ''' Controller For Uploading Images '''

    def show(self, upload: UploadS3Driver):
        ''' Show Welcome Template '''
        return upload.store('some-file.png')

Мы можем сделать этот шаг дальше, добавив родительский класс. Uploads3Driver Похоже на это на бэкэнде:

...
from masonite.contracts import UploadContract
...

class UploadS3Driver(BaseDriver, UploadContract):
    ...

Так что с этим мы можем получить тот же класс, просто используя UploadContract :

Будет хорошо знать, что то UploadContratt. не в контейнере

from masonite.contracts import UploadContract

class UploadController:
    ''' Controller For Uploading Images '''

    def show(self, upload: UploadContract):
        ''' Show Welcome Template '''

        return upload.store('some-file.png')
        # returns an upload driver

Как это работает

Это заставляет меня Uploads3Driver Класс, потому что это подкласс того, что мы ищем. Masonite обрабатывает эту логику на бэкэнде, на которой он должен получить.

Есть немного иерархии на том, что масонит должен решить.

Основы этого – это то, что он ищет сам класс Но если он не может найти это (потому что договоры не в контейнере), то он будет разрешать подкласс того, что вы ищете. Если в контейнере нет совпадения, то он будет бросать исключение.

Тестирование

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

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

from app.http.controllers.WelcomeController import WelcomeController
from masonite.request import Request
from masonite.testsuite.TestSuite import generate_wsgi

class MockView:

    def render(self, template, dictionary):
        pass

def test_welcome_controller():
    assert WelcomeController().show(MockView, Request(generate_wsgi()))

Если вы держите свои контроллеры коротко и сохраняете много ваших зависимостей в контейнере, вы можете легко создавать быстрые тесты и объекты MOCK.

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

Оригинал: “https://dev.to/masonite/masonite-python-framework-knowledge-series-part-1—understanding-auto-resolving-dependency-injection-14ma”