Научная статья на тему 'ИССЛЕДОВАНИЕ ПРИМЕНЕНИЯ ШАБЛОНА ПРОЕКТИРОВАНИЯ ВНЕДРЕНИЯ ЗАВИСИМОСТЕЙ ДЛЯ РАЗРАБОТКИ ПРИЛОЖЕНИЙ КОМАНДНОЙ СТРОКИ НА ЯЗЫКЕ ПРОГРАММИРОВАНИЯ PYTHON'

ИССЛЕДОВАНИЕ ПРИМЕНЕНИЯ ШАБЛОНА ПРОЕКТИРОВАНИЯ ВНЕДРЕНИЯ ЗАВИСИМОСТЕЙ ДЛЯ РАЗРАБОТКИ ПРИЛОЖЕНИЙ КОМАНДНОЙ СТРОКИ НА ЯЗЫКЕ ПРОГРАММИРОВАНИЯ PYTHON Текст научной статьи по специальности «Компьютерные и информационные науки»

CC BY
76
18
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
ВНЕДРЕНИЕ ЗАВИСИМОСТЕЙ / ШАБЛОНЫ ПРОЕКТИРОВАНИЯ / PYTHON / ПРОГРАММИРОВАНИЕ / РАЗРАБОТКА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ / КОМАНДНАЯ СТРОКА

Аннотация научной статьи по компьютерным и информационным наукам, автор научной работы — Могилатов Роман Константинович

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

i Надоели баннеры? Вы всегда можете отключить рекламу.

Похожие темы научных работ по компьютерным и информационным наукам , автор научной работы — Могилатов Роман Константинович

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

RESEARCH OF APPLYING OF THE DEPENDENCY INJECTION DESIGN PATTERN TO DEVELOPMENT OF COMMAND LINE APPLICATIONS IN THE PYTHON PROGRAMMING LANGUAGE

This scientific work explores the features and results of applying the dependency injection design pattern for developing command line applications in the Python programming language.

Текст научной работы на тему «ИССЛЕДОВАНИЕ ПРИМЕНЕНИЯ ШАБЛОНА ПРОЕКТИРОВАНИЯ ВНЕДРЕНИЯ ЗАВИСИМОСТЕЙ ДЛЯ РАЗРАБОТКИ ПРИЛОЖЕНИЙ КОМАНДНОЙ СТРОКИ НА ЯЗЫКЕ ПРОГРАММИРОВАНИЯ PYTHON»

6. Исмоилова Махсума Нарзикуловна, Имомова Шафоат Махмудовна. Интерполяция функции // ВЕСТНИК НАУКИ И ОБРАЗОВАНИЯ, 2020. № 3-3 (81). С. 5-8.

ИССЛЕДОВАНИЕ ПРИМЕНЕНИЯ ШАБЛОНА ПРОЕКТИРОВАНИЯ ВНЕДРЕНИЯ ЗАВИСИМОСТЕЙ ДЛЯ РАЗРАБОТКИ ПРИЛОЖЕНИЙ КОМАНДНОЙ СТРОКИ НА ЯЗЫКЕ ПРОГРАММИРОВАНИЯ PYTHON Могилатов Р.К. Email: Mogilatov6114 @scientifictext. ru

Могилатов Роман Константинович - технический руководитель, Python SoftServe Inc., г. Роли, Соединенные Штаты Америки

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

RESEARCH OF APPLYING OF THE DEPENDENCY INJECTION DESIGN PATTERN TO DEVELOPMENT OF COMMAND LINE APPLICATIONS IN THE PYTHON PROGRAMMING LANGUAGE

Mogilatov R.K.

Mogilatov Roman Konstantinovich - Technical Leader, PYTHON SOFTSERVE INC., RALEIGH, UNITED STATES OF AMERICA

Abstract: this scientific work explores the features and results of applying the dependency injection design pattern for developing command line applications in the Python programming language.

Ключевые слова: dependency injection, design patterns, Python, programming, software development, command line.

УДК 004.053

Цель исследования

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

Для проведения исследования применения шаблона проектирования внедрения зависимостей в приложениях командной строки необходимо использовать прикладную задачу: создать демонстрационное приложение командной строки для поиска видеофильмов.

Функциональные требования исследуемого приложения:

• Приложение командной строки должно использовать базу данных, содержащую следующие поля: название, год выпуска и имя режиссера

• Приложение командной строки должно использовать базу данных, поставляемую в двух форматах: csv и sqlite

• Приложение командной строки должно выполнять поиск по предоставленной базе данных по следующим полям: имя режиссера и год выпуска

• Необходимо предусмотреть возможность добавления других форматов баз данных в будущем

Данное демонстрационное приложение является адаптированным примером используемым господином Мартином Фаулеров в его статье про шаблон проектирования «внедрение зависимостей» [12].

MovieLister

а

+ movies_directed_by(director): Lisl[Movie] + movies_released_in(year): Ust[Movie]

- MovieFinder

+ find_all(): List[Movie]

---->

т

Movie

+ title: sir t- year: int + director: str

CsvMovieFinder SqliteMov eFirider

+ find_allO: List[Movie] + find_all(): List[Movie]

Рис. 1. Архитектурная диаграмма классов демонстрационного приложения Подготовка окружения для исследования

Перед началом исследования нам необходимо подготовить окружение. Для исследования мы будем использовать virtualenv - систему управления виртуальными окружениями языка программирования Python. Создадим основную директорию проекта и сделаем ее текущей рабочей директорией: mkdir movie-lister-research cd movie-lister- research

Далее создадим и активируем виртуальное окружение: python3 -m venv venv . venv/bin/activates

Настройка виртуального окружения завершена. Создание структуры исследовательского проекта

Следующим шагом исследования является создание структуры программного проекта.

Выполним создание структуры проекта в файловой системе соответственно следующей схеме:

movies/ — init

py

—_main_.py

— containers.py venv/

-config.yml

requirements.txt

Далее выполним указание зависимостей проекта. Добавим следующие строки в

файл requirements.txt: dependency-injector pyyaml pytest pytest-cov

Установим зависимости проекта в виртуальное окружение:

pip install -r requirements.txt

Создание структуры проекта завершено.

Добавление референсных данных для тестирования

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

Добавим папку data/ в текущую рабочую директорию и создадим внутри модуль fixtures.py: ./

-data/

1-fixtures.py

-movies/

--init__.py

--main_.py

-containers.py

-venv/

-config.yml

-requirements.txt

Добавим следующий исходный код в модуль fixtures.py: ......Fixtures module.......

import csv import sqlite3 import pathlib

SAMPLE_DATA = [ ('The Hunger Games: Mockingjay - Part 2', 2015, 'Francis Lawrence'), ('Rogue One: A Star Wars Story', 2016, 'Gareth Edwards'), ('The Jungle Book', 2016, 'Jon Favreau'),

]

FILE = pathlib .Path(_file_)

DIR = FILE.parent CSV_FILE = DIR / 'movies.csv' SQLITE_FILE = DIR / 'movies.db'

def create_csv(movies_data, path): with open(path, 'w') as opened_file: writer = csv.writer(opened_file) for row in movies_data: writer.writerow(row)

def create_sqlite(movies_data, path): with sqlite3.connect(path) as db: db.execute(

'CREATE TABLE IF NOT EXISTS movies ' '(title text, year int, director text)'

)

db.execute('DELETE FROM movies')

db.executemany('INSERT INTO movies VALUES (?,?,?)', movies_data)

def main():

create_csv(SAMPLE_DATA, CSV_FILE) create_sqlite(SAMPLE_DATA, SQLITE_FILE) print('OK')

if_name_== '_main_':

main()

Запустим модуль fixtures.py для создания баз данных: python data/fixtures.py Ожидаемый результат: ОК

Проверим наличие файлов movies.csv и movies.db в папке data/: ./

-data/

-fixtures.py

-movies.csv

-movies.db

-movies/

--init__.py

--main_.py

-containers.py

-venv/

-config.yml

-requirements.txt

Добавление контейнера внедрения зависимостей

Выполним добавление контейнера внедрения зависимостей. Для реализации шаблона проектирования внедрения зависимостей будем использовать программный пакет Dependency Injector.

Добавим следующие строки в файл containers.py: ......Containers module.......

from dependency_injector import containers

class Container(containers.DeclarativeContainer):

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

инициализацию контейнера зависимостей. Отредактируем файл_main_.py:

......Main module.......

from .containers import Container

def main() -> None:

if __name__ == '__main__': container = Container() main()

Добавление поддержки работы с базами данных формата csv

Добавим поддержку формата баз данных csv. Для добавления поддержки формата csv нам понадобятся следующие компоненты:

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

• Класс-сущность Movie

• Базовый класс поиска MovieFinder

• Класс-реализация поиска формате csv ■

• Класс MovieLister

CsvMovieFinder

MovieLister

а

+ mov es_directed_by(director): List[Movie] + movies_releasedJn(year): List[Movie]

- MovieFinder

+ find_ali(): Lia[Movie]

CsvMovieFinder SqliteMovieFinder

+ find_all(): List[Movie] + find_all(): List[Movie]

Рис. 2. Архитектурная диаграмма классов на этапе добавления формата баз данных csv Создаем файл entities.py в пакете movies:

./

— data/

-fixtures.py

— movies.csv

— movies.db movies/

—_init__.py

—_main_.py

— containers.py -entities.py

venv/ config.yml requirements.txt И добавляем в него следующие строки: ......Movie entities module.......

class Movie:

def_init__(self, title: str, year: int, director: str):

self.title = str(title) self.year = int(year) self.director = str(director)

def_repr_(self):

return '{0}(title={1}, year={2}, director={3})'.format(

self._class_._name_,

repr(self.title),

repr(self.year), repr(self.director),

)

Добавляем фабрику сущностей для объектов класса Movie. Отредактируем файл containers.py:

......Containers module.......

from dependency_injector import containers, providers from . import entities

class Container(containers.DeclarativeContainer): movie = providers.Factory(entities.Movie)

Переходим к созданию поисковых классов. Добавим файл finders.py в пакет movies: ./

-data/

-fixtures.py

-movies.csv

-movies.db

-movies/

--init__.py

--main_.py

-containers.py

-entities.py

-finders.py

-venv/

-config.yml

-requirements.txt

И добавим в него следующие строки: ......Movie finders module.......

import csv

from typing import Callable, List from .entities import Movie

class MovieFinder:

def_init__(self, movie_factory: Callable[..., Movie]) -> None:

self._movie_factory = movie_factory def find_all(self) -> List[Movie]: raise NotImplementedError()

class CsvMovieFinder(MovieFinder):

def_init__(

self,

movie_factory: Callable[..., Movie], path: str, delimiter: str, ) -> None:

self._csv_file_path = path self._delimiter = delimiter

super()._init_(movie_factory)

def find_all(self) -> List[Movie]:

with open(self._csv_file_path) as csv_file:

csv_reader = csv.reader(csv_file, delimiter=self._delimiter) return [self._movie_factory(*row) for row in csv_reader] Выполним добавление поискового объекта класса для работы с csv базами данных в контейнер зависимостей. Отредактируем файл containers.py: ......Containers module.......

from dependency_injector import containers, providers from . import finders, entities

class Container(containers.DeclarativeContainer): config = providers.Configuration() movie = providers.Factory(entities.Movie) csv_finder = providers.Singleton( finders.CsvMovieFinder, movie_factory=movie.provider, path=config.finder.csv.path, delimiter=config.finder.csv.delimiter,

)

Поисковому класса для формата csv необходима фабрика объектов-сущностей Movie. Она необходима для создания объектов-сущностей при чтении строк из базы данных csv. Чтобы выполнить внедрение зависимости фабрики, используем атрибут фабрики .provider. Это методика называется делегированием провайдера. Если мы передадим фабрику Movie в качестве зависимости не указав атрибут .provider, она будет вызываться при создании компонента csv_finder и будет внедрен объект Movie. В данном случае, указывая атрибут .provider, будет внедрена сама фабрика. Данный подход так же работает и для других типов провайдеров.

CSV Finder также имеет несколько зависимостей от параметров конфигурации. Мы добавили провайдер конфигурации для обеспечения этих зависимостей. Далее добавим конфигурационные значения. Отредактируем файл config.yml: finder: csv:

path: "data/movies.csv" delimiter: ","

Далее отредактируем основную функцию приложения для связывания провайдера конфигурации с содержимым конфигурационного файла. Отредактируем файл

_main_.py:

......Main module.......

from .containers import Container

def main() -> None:

if __name__ == '__main__': container = Container() container.config.from_yaml('config.yml')

main()

Далее выполняем создание класса MovieLister. Созданим файл listers.py в пакете movies: ./

-data/

-fixtures.py

-movies.csv

1-movies.db

-movies/

--init__.py

--main_.py

-containers.py

-entities.py

-finders.py

-listers.py

-venv/

-config.yml

-requirements.txt

И добавим в него следующие строки: ......Movie listers module.......

from .finders import MovieFinder

class MovieLister:

def_init (self, movie_finder: MovieFinder):

self._movie_finder = movie_finder def movies_directed_by(self, director): return [

movie for movie in self._movie_finder.find_all() if movie.director == director

]

def movies_released_in(self, year): return [

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

movie for movie in self._movie_finder.find_all() if movie.year == year

]

Добавим фабрику объектов класса MovieLister в контейнер внедрения зависимостей. Отредактируем файл containers.py: ......Containers module.......

from dependency_injector import containers, providers from . import finders, listers, entities

class Container(containers.DeclarativeContainer): config = providers.Configuration() movie = providers.Factory(entities.Movie) csv_finder = providers.Singleton( finders. CsvMovieFinder, movie_factory=movie.provider, path=config.finder.csv.path, delimiter=config.finder.csv.delimiter,

)

lister = providers.Factory( listers.MovieLister, movie_finder=csv_finder,

)

Создание всех компонентов завершено. Выполним внедрение зависимости lister в

основную функцию приложения main(). Отредактируем файл_main_.py:

......Main module.......

import sys

from dependency_injector.wiring import inject, Provide from .listers import MovieLister from .containers import Container

@inject

def main(lister: MovieLister = Provide[Container.lister]) -> None:

if_name_== '_main_':

container = Container() container.config.from_yaml('config.yml')

container.wire(modules=[sys.modules[_name_]])

main()

Зависимость lister будет передаваться при каждом вызове функции main(). Добавим функциональную нагрузку в функцию main(). При выполнении функции main() будем виводить записи, выпущенные режиссером Фрэнсисом Лоуренсом, и

записи, выпущенные в 2016 году. Отредактируем файл_main_.py:

......Main module.......

import sys

from dependency_injector.wiring import inject, Provide from .listers import MovieLister from .containers import Container

@inject

def main(lister: MovieLister = Provide[Container.lister]) -> None: print('Francis Lawrence movies:')

for movie in lister.movies_directed_by('Francis Lawrence'):

print('\t-', movie) print('2016 movies:')

for movie in lister.movies_released_in(2016): print('\t-', movie)

if_name_== '_main_':

container = Container() container.config.from_yaml('config.yml')

container.wire(modules=[sys.modules[_name_]])

main()

Запустим приложение в интерфейса командной строки: python -m movies Ожидаемый результат: Francis Lawrence movies:

- Movie(title='The Hunger Games: Mockingjay - Part 2', year=2015, director='Francis Lawrence')

2016 movies:

- Movie(title='Rogue One: A Star Wars Story', year=2016, director='Gareth Edwards')

- Movie(title='The Jungle Book', year=2016, director='Jon Favreau')

На данном этапе исследуемое приложение может работать с базой данных в формате csv. Мы также хотим поддерживать формат базы данных sqlite. Выполним это в следующем разделе исследования.

Добавление поддержки работы с базами данных формата sqlite

Добавим поддержку формата базы данных sqlite. Отредактируем файл finders.py: ......Movie finders module.......

import csv import sqlite3

from typing import Callable, List from .entities import Movie

class MovieFinder:

def_init__(self, movie_factory: Callable[..., Movie]) -> None:

self._movie_factory = movie_factory def find_all(self) -> List[Movie]: raise NotImplementedError()

class CsvMovieFinder(MovieFinder):

def_init__(

self,

movie_factory: Callable[..., Movie], path: str, delimiter: str, ) -> None:

self._csv_file_path = path self._delimiter = delimiter

super()._init_(movie_factory)

def find_all(self) -> List[Movie]:

with open(self._csv_file_path) as csv_file:

csv_reader = csv.reader(csv_file, delimiter=self._delimiter) return [self._movie_factory(*row) for row in csv_reader]

class SqliteMovieFinder(MovieFinder):

def_init_(

self,

movie_factory: Callable[..., Movie], path: str, ) -> None:

self._database = sqlite3.connect(path)

super()._init_(movie_factory)

def find_all(self) -> List[Movie]: with self._database as db:

rows = db.execute('SELECT title, year, director FROM movies') return [self._movie_factory(*row) for row in rows] Далее добавим ново-созданный компонент в контейнер зависимостей и изменим внедрение зависимостей компонента lister для использования ново-добавленного компонента:

......Containers module.......

from dependency_injector import containers, providers from . import finders, listers, entities

class Container(containers.DeclarativeContainer): config = providers.Configuration() movie = providers.Factory(entities.Movie) csv_finder = providers.Singleton(

finders. CsvMovieFinder, movie_factory=movie.provider, path=config.finder.csv.path, delimiter=config.finder.csv.delimiter,

)

sqlite_finder = providers.Singleton( finders.SqliteMovieFinder, movie_factory=movie.provider, path=config.finder.sqlite.path,

)

lister = providers.Factory( listers.MovieLister,

movie_finder=sqlite_finder,

)

Компонент для работы с базами данных sqlite имеет зависимость от конфигурационных значений, которые хранятся в конфигурационном файле. Обновим конфигурационный файл. Отредактируем файл config.yml: finder: csv:

path: "data/movies.csv"

delimiter: "," sqlite:

path: "data/movies.db"

На данном этапе приложение поддерживает формат баз данных sqlite. Выполним проверку работоспособности приложения. Выполним следующую команду в интерфейсе командной строки: python -m movies Ожидаемый результат: Francis Lawrence movies:

- Movie(title='The Hunger Games: Mockingjay - Part 2', year=2015, director='Francis Lawrence')

2016 movies:

- Movie(title='Rogue One: A Star Wars Story', year=2016, director='Gareth Edwards')

- Movie(title='The Jungle Book', year=2016, director='Jon Favreau') Добавление вариативности используемой реализации

Исследуемое приложение теперь поддерживает оба формата баз данных: csv и sqlite. Для изменения формата базы данных необходимо вносить изменения в исходный код приложения. Это значительно увеличивает затраты на сопровождение приложения. Этих изменений можно избежать за счет применения провайдера Selector программного комплекса Dependency Injector.

Для реализации переключателя формата баз данных будем использовать переменную окружения операционной системы MOVIE_FINDER_TYPE. Данная переменная окружения может принимать следующие значения:

• При MOVIE_FINDER_TYPE=csv, приложение использует формат csv

• При MOVIE_FINDER_TYPE=sqlite, приложение использует формат sqlite Добавим провайдер Selector в контейнер зависимостей. Отредактируем файл

containers.py:

......Containers module.......

from dependency_injector import containers, providers from . import finders, listers, entities

class Container(containers.DeclarativeContainer):

config = providers.Configuration() movie = providers.Factory(entities.Movie) csv_finder = providers.Singleton( finders. CsvMovieFinder, movie_factory=movie.provider, path=config.finder.csv.path, delimiter=config.finder.csv.delimiter,

)

sqlite_finder = providers.Singleton( finders. SqliteMovieFinder, movie_factory=movie.provider, path=config.finder.sqlite.path,

)

finder = providers.Selector( config.finder.type, csv=csv_finder, sqlite=sqlite_finder,

)

lister = providers.Factory( listers.MovieLister,

movie_finder=finder,

)

В качестве переключателя используем параметр конфигурационного провайдера config.finder.type. Если его значение - csv, используется провайдер csv_finder, если sqlite - провайдер sqlite_finder.

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

Далее добавим считывание значения переключателя config.finder.type из

переменной окружения MOVIE_FINDER_TYPE. Отредактируем файл_main_.py:

......Main module.......

import sys

from dependency_injector.wiring import inject, Provide from .listers import MovieLister from .containers import Container

@inject

def main(lister: MovieLister = Provide[Container.lister]) -> None: print('Francis Lawrence movies:')

for movie in lister.movies_directed_by('Francis Lawrence'):

print('\t-', movie) print('2016 movies:')

for movie in lister.movies_released_in(2016): print('\t-', movie)

if __name__ == '__main__': container = Container() container.config.from_yamI('config.ymT)

container.config.finder.type.from_env('MOVIE_FINDER_TYPE')

container.wire(modules=[sys.modules[_name_]])

main()

Выполним следующие команды в интерфейсе командной строки: MOVIE_FINDER_TYPE=csv python -m movies MOVIE_FINDER_TYPE=sqlite python -m movies Ожидаемый результат выполнения каждой команды:

Francis Lawrence movies:

- Movie(title='The Hunger Games: Mockingjay - Part 2', year=2015, director='Francis Lawrence')

2016 movies:

- Movie(title='Rogue One: A Star Wars Story', year=2016, director='Gareth Edwards')

- Movie(title='The Jungle Book', year=2016, director='Jon Favreau') Исследуемое приложение поддерживает вариативность внедрения зависимостей

на базе переменных окружения.

Автоматическое модульное тестирование

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

Будем использовать программные пакеты pytest и coverage для запуска процесса автоматизированного тестирования и измерения процента покрытия. Создаем файл tests.py в пакете movies: ./

-data/

-fixtures.py

-movies.csv

-movies.db

-movies/

--init__.py

--main_.py

-containers.py

-entities.py

-finders.py

-listers.py

-tests.py

-venv/

-config.yml

-requirements.txt

И добавляем в него следующие строки: ......Tests module.......

from unittest import mock import pytest

from .containers import Container

@pytest.fixture def container():

container = Container() container.config.from_dict({ 'finder': { 'type': 'csv', 'csv': { 'path': '/fake-movies.csv', 'delimiter': ',',

'sqlite': { 'path': '/fake-movies.db',

},

},

})

return container

def test_movies_directed_by(container) : finder_mock = mock.Mock() finder_mock.find_all.retum_value = [

container.movie('The 33', 2015, 'Patricia Riggen'), container.movie('The Jungle Book', 2016, 'Jon Favreau'),

]

with container.finder.override(finder_mock): lister = container.lister()

movies = lister.movies_directed_by('Jon Favreau') assert len(movies) == 1 assert movies[0].title == 'The Jungle Book'

def test_movies_released_in(container) : finder_mock = mock.Mock() finder_mock.find_all.return_value = [

container.movie('The 33', 2015, 'Patricia Riggen'), container.movie('The Jungle Book', 2016, 'Jon Favreau'),

]

with container.finder.override(finder_mock): lister = container.lister() movies = lister.movies_released_in(2015) assert len(movies) == 1 assert movies[0].title == 'The 33' Для запуска автоматического тестирования выполняем команду в интерфейсе командной строки:

pytest movies/tests.py --cov=movies Ожидаемый результат:

platform darwin -- Python 3.8.3, pytest-5.4.3, py-1.9.0, pluggy-0.13.1 plugins: cov-2.10.0 collected 2 items

movies/tests.py .. [100%]

----------coverage: platform darwin, python 3.8.5-final-0-----------

Name Stmts Miss Cover

movies/_init .py 0 0 100%

movies/_main_.py 18 18 0%

movies/containers.py 9 0 100%

movies/entities.py 7 1 86%

movies/finders.py 26 13 50%

movies/listers.py 8 0 100%

movies/tests.py 24 0 100%

TOTAL 92 32 65%

Рассмотрим результаты тестирования. Все основные модули покрыты автоматическими тестами. Общий процент покрытия составляет 65%. Это является высоким значением так как диапазон нормальных значений по индустрии на 2021 год является на уровне 40-60% покрытия.

Вывод

Мы исследовали особенности и результаты применения шаблона применения

внедрения зависимостей для разработки приложения интерфейса командной строки применяя программный комплекс Dependency Injector.

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

Для реализации вариативности внедрения зависимостей на основе переменных окружения операционной системы был использован провайдер Selector программного комплекса Dependency Injector. Это помогло снизить уровень затрат на сопровождение приложения. Так же это реализует требование расширяемости относительно добавления других форматов баз данных в будущем.

Для внедрения зависимости в основную функцию приложения main() было использовано связывание (wiring) и декоратор @inject программного комплекса Dependency Injector. Это помогло улучшить тестируемость приложения и добиться 65% покрытия кода автоматическими модульными тестами.

Аномалий или деградаций при проведении исследования не обнаружено.

Список литературы /References

1. Refactoring: Improving the Design of Existing Code by Martin Fowler, Kent Beck, John Brant, William Opdyke, Don Roberts, Erich Gamma (Foreword) // Addison-Wesley Professional; 1st edition (June 28, 1999).

2. Patterns of Enterprise Application Architecture by Martin Fowler. Implementation Patterns by Kent Beck // Addison-Wesley Professional; 1st edition (October 23, 2007).

3. The Pragmatic Programmer: From Journeyman to Master by Andrew Hunt, David Thomas // Addison-Wesley Professional; 1st edition (October 1, 1999).

4. Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin // Pearson; 1st edition (August 1, 2008).

5. Building Microservices: Designing Fine-Grained Systems by Sam Newman // O'Reilly Media; 1st edition (February 2, 2015).

6. Design Patterns: Elements of Reusable Object-Oriented Software by GoF - Gang of Four - Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides // Addison-Wesley Professional; 1st edition (November 10, 1994).

7. Refactoring: Improving the Design of Existing Code (2nd Edition) by Martin Fowler // Addison-Wesley Professional; 2nd edition (November 30, 2018).

8. Domain-Driven Design: Tackling Complexity in the Heart of Software by Eric Evans // Addison-Wesley Professional; 1st edition (August 20, 2003).

9. The Mythical Man-Month: Essays on Software Engineering, Anniversary Edition (2nd Edition) by Brooks Jr., Frederick P. // Addison-Wesley Professional; Anniversary edition (August 2, 1995).

10. The Innovation Algorithm: TRIZ, systematic innovation and technical creativity (1st Edition) by Genrich Altshuller. // Technical Innovation Ctr; 1st edition (March 1, 1999).

11. Software Estimation: Demystifying the Black Art by Steve McConnell. // Microsoft Press; 1st edition (March 1, 2006).

12. Inversion of Control Containers and the Dependency Injection pattern. [Электронный ресурс]. Режим доступа:https://martinfowler.com/articles/injection.html/ (дата обращения: 18.06.2021).

13. Dependency Injector (Documentation). [Электронный ресурс]. Режим доступа: https://python-dependency-injector.ets-labs.org/ (дата обращения: 18.06.2021).

14. Dependency Injector (GitHub). [Электронный ресурс]. Режим доступа:https://github.com/ets-labs/python-dependency-injector/ (дата обращения: 18.06.2021).

15. Dependency Injector (Python Package Index). [Электронный ресурс]. Режим доступа: https://pypi.org/project/dependency-injector/ (дата обращения: 18.06.2021).

16. Dependency injection and inversion of control in Python. [Электронный ресурс]. Режим доступа:https://python-dependency-injector.ets-labs.org/introduction/di_in_python.html/ (дата обращения: 18.06.2021).

17. Dependency injection. [Электронный ресурс]. Режим доступа:https://en.wikipedia.org/wiki/Dependency_injection/ (дата обращения: 18.06.2021).

МЕТОДЫ ОБУЧЕНИЯ ИНС

1 2 3

Кирпиков М.В. , Немовленко А.Е. , Макарова А.В. Email: Kirpikov6114@scientifictext.ru

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

1Кирпиков Михаил Викторович - студент магистратуры, кафедра технологии и оборудования лесопромышленного производства; 2Немовленко Ангелина Евгеньевна - студент специалитета; 3Макарова Анастасия Владимировна - студент специалитета, кафедра систем автоматического управления, Мытищинский филиал Московский государственный технический университет им. Н.Э. Баумана,

г. Мытищи

Аннотация: в данной статье авторы рассматривают искусственные нейронные сети, имеющие несколько видов и способов классификаций, а также их структуру. Уделяют внимание методам обучения, которые могут быть применены для навигации беспилотных летательных аппаратов: метод Холтона, градиентный метод, ЛП - поиск, Метод Дэвидона - Флетчера - Пауэлла. А также приведена информация о применениях искусственных нейронных сетей. Тема статьи является актуальной, поскольку существуют системы, которым необходима дополнительная оптимизация.

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

ANN TRAINING METHODS Kirpikov M.V.1, Nemovlenko A.E.2, Makarova A.V.3

1Kirpikov Mikhail Vladimirovich - master's Student, DEPARTMENT OF TECHNOLOGY AND EQUIPMENT FOR TIMBER INDUSTRY; 2Nemovlenko Angelina Evgenievna - Student of specialty; 3Makarova Anastasia Vladimirovna - Student of specialty, DEPARTMENT OF AUTOMATIC CONTROL SYSTEMS, MYTISCHI BRANCH MOSCOW STATE TECHNICAL UNIVERSITY NAMED AFTER N.E. BAUMAN,

MYTISHCHI

Abstract: in this article, the authors consider artificial neural networks that have several types and methods of classification, as well as their structure. They pay attention to teaching methods that can be applied to navigation of unmanned aerial vehicles: Holton method, gradient method, LP - search, Davidon - Fletcher - Powell method. It also provides information on the use of artificial neural networks. The topic of the article is relevant, since there are systems that need additional optimization.

Keywords: artificial neural networks, neurons, navigation of unmanned aerial vehicles, signal characteristics, training methods.

УДК 62-523

i Надоели баннеры? Вы всегда можете отключить рекламу.