Technical Leader в SoftServe
  • Топик для поиска менторов

    Отлично. На счет ошибок:

    23:1: E265 block comment should start with ’# ’
    24:33: E262 inline comment should start with ’# ’

    — Не знаю как исправить. Что-то странное. Думаю нужно пересмотреть количество коментов. Постарайся их минимизировать. Если правильно именовать и структурировать, коменты не понадобятся.

    На счет radon — очень хорошо.

    Насчет

    F 77:0 main — C

     — если еще не разобралась с цикломатической сложностью, дело в количестве условных блоков. Нужно стараться разбить main() на набор более мелких функций.

  • Топик для поиска менторов

    Привет, твое сообщение пришло. Отправил тебе свой контакт в телеграмме, пиши туда.

    Мой профиль в менторботе — t.me/...​ot?start=mentor-157648379

  • Топик для поиска менторов

    Написал в саппорт

    Поддержал: Юлія Патлата
  • Топик для поиска менторов

    Ничего не получил. Похоже нужно репортить на ДОУ баг :)

  • Топик для поиска менторов

    Ты не получала личного сообщения? Продублирую здесь:

    1) Перенеси код из if __name__ == ’__main__’ в функцию main().
    2) Убери print() из исключений. Параметры в них тоже лишние.
    3) Прогони свой скрипт через утилиту pypi.org/project/flake8 с плагином pypi.org/...​roject/flake8-docstrings. Это позволит привести код в соответствие со стандартами PEP8 и PEP257.
    4) Прогони свой код через утилиту pypi.org/project/radon. Рефактори пока не получится добиться индекса A для всех функций.

    Поддержал: Юлія Патлата
  • Топик для поиска менторов

    Заинтересовался идеей и пошёл почитать код на гитхабе. Могу дать пару советов, пиши в личку.

    Поддержал: Юлія Патлата
  • Dependency Injector 4.0 — упрощенная интеграция с другими Python фреймворками

    Да. Вот как выглядит контейнер побольше:

    """Containers module."""
    
    import logging.config
    import sqlite3
    
    import boto3
    from dependency_injector import containers, providers
    
    from . import services
    
    
    class Container(containers.DeclarativeContainer):
    
        config = providers.Configuration()
    
        configure_logging = providers.Callable(
            logging.config.fileConfig,
            fname='logging.ini',
        )
    
        # Gateways
    
        database_client = providers.Singleton(
            sqlite3.connect,
            config.database.dsn,
        )
    
        s3_client = providers.Singleton(
            boto3.client,
            service_name='s3',
            aws_access_key_id=config.aws.access_key_id,
            aws_secret_access_key=config.aws.secret_access_key,
        )
    
        # Services
    
        user_service = providers.Factory(
            services.UserService,
            db=database_client,
        )
    
        auth_service = providers.Factory(
            services.AuthService,
            db=database_client,
            token_ttl=config.auth.token_ttl.as_int(),
        )
    
        photo_service = providers.Factory(
            services.PhotoService,
            db=database_client,
            s3=s3_client,
        )
    

    Factory провайдер photo_service зависит от от Singleton-провайдеров s3_client и database_client и т. д.

    При вызове провайдер photo_service будет всегда создавать новый объект, а в качестве зависимостей будут передаваться единожды созданные объекты провайдеров database_client и s3_client.

  • Dependency Injector 4.0 — упрощенная интеграция с другими Python фреймворками

    Если под управлением ресурсами имеется ввиду время жизни объектов, то да — за счет разных провайдеров:

    • Factory — всегда создает новый объект
    • Singleton — создает объект единожды и переиспользует при последующих обращениях
    • ThreadLocalSingleton — создает объект единожды для каждого потока
    • Selector — выбирает что создать на основе значения конфигурации

    Про провайдеры можно почитать тут.

    Про другие фичи можно почитать тут.

  • Dependency Injector — dependency injection фреймворк для Python

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

    В Python есть typing. Он используется в примерах в посте.

  • Dependency Injector — dependency injection фреймворк для Python

    Переходы по Ctrl + клик работают во всех примерах в этом посте.

    Это достигается за счет 2-х вещей:

    • Использование типизации в коде. В метода Service.__init__(self, api_client: ApiClient) можно нажать на ApiClient и перейти к его определению.
    • Использование связи по ссылке в контейнере. В Dependency Injector не используются строковые идентификаторы. Дизайн построен на ссылочной связи. Когда указываешь зависимость используешь объект другого провайдера, а не строку-идентификатор. Это сделано специально чтобы Ctrl + клик работал и можно было перейти к зависимости.
    Вот как раз гибкость и понятность кода обычно противоположны. И любые абстракции очень тяжело разруливать.

    В PEP20 есть такой принцип «Complex is better than complicated». Вот пример иллюстрации: pbs.twimg.com/...​media/Bky1fNJCQAAztUg.png

    Бывают простые (1), сложные (2) и сложные и запутанные проекты (3). Принцип dependency injection помогает перейти от сложного и запутанного проекта (3) к просто сложному (2).

    Когда у вас будет контейнер со всеми компонентами и их зависимости по проекту нужно будет гораздо реже передвигаться поиском.

    Поддержали: Dmitriy Gordon, Sergii Buinytskyi
  • Dependency Injector — dependency injection фреймворк для Python

    на серйознішу мову

    Python — несерьезный язык?

  • Dependency Injector — dependency injection фреймворк для Python

    На счет контрибьюторов.

    Создатель pinject не занимается своим фреймворком с 14 года. Я занимаюсь Dependency Injector постоянно. Не всегда много контрибьюторов == хорошая поддержка. Наличие лидера в опенсорс проекте — решающий фактор.

    Я поддерживаю Dependency Injector самостоятельно. Непофикшенных багов в нем нет. Простые баги фикшу за часы. Фичи занимают дни или недели. Спорные фичи могут занять несколько месяцев так как функционал добавляю аккуратно. Если сомневаюсь в необходимости или потенциальной опасности фичи, даю автору временное решение и оставляю ее «на подумать» перед добавлением в фреймворк.

    Если хотите присоединиться, пишите в личку. Помощи буду рад.

  • Dependency Injector — dependency injection фреймворк для Python

    Приятно, когда твой фреймворк сравнивают с Ansible. Это первый раз, спасибо :)

    Количество даунлоадов ни о чем

    «ни о чем» — неконструктивный аргумент. Dependency Injector скачивают в 10 раз больше, чем pinject.

  • Dependency Injector — dependency injection фреймворк для Python

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

  • Dependency Injector — dependency injection фреймворк для Python

    Я переписывал Dependency Injector на Cython по двум причинам:

    • бросал тогда курить
    • CV-driven development

    Как бонус удалось получить неплохой прирост производительности.

    Проблем при переписывании было немало. После тоже. Второй бы раз хорошо подумал над этим шагом.

    Поддержал: Andriy Maletsky
  • Dependency Injector — dependency injection фреймворк для Python

    Да, есть такой. Переходите на Dependency Injector, он лучше чем pinject.

    Dependency Injector отличается от pinject такими вещами:

        У pinject нет понятия контейнера. Это минус, так как без контейнера нет возможности посмотреть на приложение целиком и понять где что используется. У Dependency Injector эта возможность есть.
        У pinject есть авторесолвинг зависимостей по именам. Это плохой механизм. Он заставляет писать код по правилам именования pinject, а не по правилам здравого смысла. Кроме того что это неудобно, в определенный момент это перестает работать. Тогда приходится добавлять исключения в виде binding specs. Код превращается в кашу так как уже не понятно где используется авторесолвинг, а где исключение в binding specs. Dependency injector построен на принципе «явное лучше неявного (PEP20)» и такими минусами не обладает. Авторесолвинга по именам или типам в Dependency Injector нет специально.
        У pinject есть аннотации (хотя в начале документации они пишут что нет). Аннотации плохой механизм. Наличие аннотаций сборки в коде косвенно противоречит принципу dependency injection. Мы применяем dependency injection чтобы убрать из кода информацию о сборке, а аннотации ее косвенно приносят обратно. Кроме того аннотации привязывают ваш код к фреймворку pinject. В Dependency Injector аннотаций нет специально. Декоратор @inject был в первой версии — убрал его во второй версии with opened eyes. Люди начинают им пользоваться, а когда проект вырастает — страдают и ругаются.
        Dependency Injector быстрее pinject. Dependency Injector написан на Cython и не приводит к деградации производительности. Pinject это чистый Python. До того как я переписал Dependency Injector на Cython он был в 50 раз медленнее.
        Dependency Injector популярнее, чем pinject. Dependency Injector скачивают с PyPI 200 тыс. раз в месяц, а pinject — 19 тыс.. Звездочек на гитхабе у pinject больше, но динамика прироста лучше у Dependency Injector.
    1. Dependency Injector — dependency injection фреймворк для Python

      Да, нужно было это описать. Я уже пошел и поменял README. Пост трогать уже не буду для исторической сохранности :) Еще раз спасибо за вопросы

      Поддержал: Bob Arch
    2. Dependency Injector — dependency injection фреймворк для Python

      Классные вопросы, спасибо. Отвечаю:

      1. Все зливати в один конфіг не завжди зручно.

      Да, правда. Dependency Injector поддерживает работу с несколькими контейнерами. Есть 2 варианта:

      1. Контейнер для каждого слоя: Core, Infrastructure, Gateways, Services, WebApi (Пример)
      2. Контейнер для пакета (контекста): Users, Photos, Billing, Payment (Пример)
      Навіщо цілий фреймворк для такої речі.

      Когда применяешь dependency injection код сборки объектов становится вот таким:

      service = Service(ApiClient(config['api_key'], config['timeout']))
      

      Такой код со временем дублируется и менять структуру становится тяжелее. Dependency Injector помогает описать сборку в одном месте и убрать дублирование:

      service = container.service()
      

      Еще Dependency Injector дает бонус в виде переопределения любого провайдера с помощью метода .override():

      from unittest import mock
      
      
      with container.api_client.override(mock.Mock()):
          service = container.service()
          assert isinstance(service.api_client, mock.Mock)
      

      Это помогает при тестировании. Можно применять для настройки проекта для работы в разных окружениях: подставить стабы для API на дев и стейдж.

      Архітектура підбирається під конкретний проект індивідуально і має, як правило, свої особливості.

      Dependency Injector не привязывает к определенной архитектуре. Он помогает собирать код, который написан по принципу dependency injection. Его можно применять для построения проекта с нуля и для части проекта. Такое обычно происходит при пошаговом рефакторинге.

      Поддержал: Nikolay Baluk
    3. Telegram бот для поиска менторов

      Нет. Проект с закрытым исходным кодом. Планируем сделать технический пост. В нём расскажем как все устроено.

    4. Телеграм чат для розробників C/C++/Rust

      Если учитесь или можете помочь с обучением другим приходите в МенторБот 🥋

      t.me/devmentorbot

    ← Сtrl 12 Ctrl →