Научная статья на тему 'Инверсия управления и внедрение зависимостей'

Инверсия управления и внедрение зависимостей Текст научной статьи по специальности «Компьютерные и информационные науки»

CC BY
704
82
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
ИНВЕРСИЯ УПРАВЛЕНИЯ / ВНЕДРЕНИЕ ЗАВИСИМОСТЕЙ / CONSTRUCTOR INJECTION / METHOD INJECTION / PROPERTY INJECTION

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

В статье рассматривается один из актуальных принципов объектно-ориентированного программирования Inversion of Control, суть которого в том, что каждый компонент системы должен быть как можно более изолированным от других, и его конкретную реализацию внедрение зависимостей.

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

Текст научной работы на тему «Инверсия управления и внедрение зависимостей»

МЕЖДУНАРОДНЫЙ НАУЧНЫЙ ЖУРНАЛ «СИМВОЛ НАУКИ» №10-1/2016 ISSN 2410-700Х_

УДК 519.683.8

Уваров Артем Николаевич

студент ФМиИТ

ФГБОУ ВО «МГУ им. Н.П. Огарева», г. Саранск, РФ E-mail: uvarov.artem16@yandex.ru

ИНВЕРСИЯ УПРАВЛЕНИЯ И ВНЕДРЕНИЕ ЗАВИСИМОСТЕЙ.

Аннотация

В статье рассматривается один из актуальных принципов объектно-ориентированного программирования Inversion of Control, суть которого в том, что каждый компонент системы должен быть как можно более изолированным от других, и его конкретную реализацию - внедрение зависимостей.

Ключевые слова

Инверсия управления, внедрение зависимостей, Constructor Injection, Method Injection, Property Injection.

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

Inversion of Control (инверсия управления) — это некий абстрактный принцип объектно-ориентированного программирования, набор рекомендаций для написания слабо связанного кода, суть которого в том, что каждый компонент системы должен быть как можно более изолированным от других, не полагаясь в своей работе на детали конкретной реализации других компонентов [1].

Согласно подходу инверсии управления, если у нас есть клиент, который использует некий сервис, то он должен делать это не напрямую, а через посредника (рис. 1) [2].

Рисунок 1 - Схема взаимодействия компонентов IoC

Инверсия управления является ключевым различием между фреймворком и библиотекой. Библиотека - набор определенных функций, используемых для разработки. Фреймворк воплощает в себе некоторый абстрактный дизайн со встроенным поведением. Классическая модель подразумевает, что вызывающий код контролирует внешнее окружение и время и порядок вызова библиотечных методов. Однако в случае фреймворка обязанности меняются местами: фреймворк предоставляет некоторые точки расширения, через которые он вызывает определенные методы пользовательского кода.

Не смотря на все свои очевидные плюсы, инверсия управления является лишь общим набором рекомендаций, что предполагает наличие более конкретных паттернов, имеющих своим основанием IoC. Таких паттернов три:

Factory Method, Service Locator, Dependency Injection.

Рассмотрим одну из наиболее интересных реализаций IoC - внедрение зависимостей.

_МЕЖДУНАРОДНЫЙ НАУЧНЫЙ ЖУРНАЛ «СИМВОЛ НАУКИ» №10-1/2016 ISSN 2410-700Х_

Внедрение зависимостей (DI, Dependency Injection) - это механизм передачи классу его зависимостей. Существует несколько конкретных видов или паттернов внедрения зависимостей: внедрение зависимости через конструктор (Constructor Injection), через метод (Method Injection) и через свойство (Property Injection) [1].

class MessageProcessor

{

private readonly IMessageSender messageSender;

// Constuctor Injection: передача обязательной зависимости

public MessageProcessor(IMessageSender messageSender) {

this.messageSender = messageSender;

Logger = LogManager.DefaultLogger; }

// Method Injection: передача обязательных зависимостей метода

public void SendMessage(Message message, IMessageFormatter formatter) {

Logger.Info("Sending message...");

var formattedMessage = formatter.Format(message);

this.messageSender.SendMessage(formattedReport);

Logger.Info("Message has been sent"); }

// Property Injection: установка необязательных "инфраструктурных" зависимостей

public ILogger Logger { get; set; } }

Каждый вид внедрения зависимостей предназначен для решения определенных задач. Через конструктор передаются все зависимости, требуемые некоторому классу, в качестве параметров конструктора, представленных в виде интерфейсов или абстрактных классов (IMessageSender - зависимость класса MessageProcessor). Передача зависимостей через конструктор является предпочтительным способом внедрения зависимостей, поскольку в этом случае проще всего обеспечить четкий контракт между классом и его клиентами. В этом случае, классу просто контролировать все обязательные зависимости и генерировать исключение, в случае необходимости. Клиенту, с другой стороны, четко видно, какое количество зависимостей ему необходимо предоставить (создать нужный «контекст» исполнения), чтобы «сервис» выполнил свою работу [4].

Через свойства должны устанавливаться лишь необязательные зависимости (обычно, инфраструктурные), для которых существует значение по умолчанию (свойство Logger содержит разумное значение по умолчанию, но может быть заменено позднее). Суть в том, что необязательная зависимость, требуемая некоторому классу, может быть переопределена вызывающим кодом путем установки ее через свойство. Передачу зависимости через свойство следует применять только для необязательных зависимостей, для которых существует разумная реализация по умолчанию, известная классу сервиса; при этом должна существовать возможность изменить зависимость во время исполнения сервиса без серьезных последствий. Проблема использования Property Injection для обязательных зависимостей заключается в том, что это очень сильно увеличивает сложность класса. Класс с тремя полями, каждое из которых может быть null приводит к 8 разным комбинациям состояния объекта. Попытка проверить состояние в теле каждого открытого метода приводит к ненужному скачку сложности [4].

Через метод передаются зависимости, которые нужны лишь одному методу, а не всем методам класса

_МЕЖДУНАРОДНЫЙ НАУЧНЫЙ ЖУРНАЛ «СИМВОЛ НАУКИ» №10-1/2016 ISSN 2410-700Х_

(IMessageFormatter необходим только методу отправки отчета, а не классу MessageProcessor целиком). Рассмотрим небольшой пример:

public class Engine {

public int GetCapacity() {

return 98; }

}

public class Car {

private readonly Engine engine;

public Car() {

engine = new Engine(); }

public void ShowPower() {

Console.WriteLine("Engine power: {0}", engine.GetCapacity ()); }

}

class Program {

static void Main() {

Car car = new Car();

car.ShowPower(); }

}

С синтаксической и логической точек зрения в этом примере все в порядке. Код отлично отработает и в нем абсолютно ничего не надо трогать, если это часть программы состоящей из пяти классов. Вопросы возникают, когда такой код появляется в реальном проекте, насчитывающем десятки классов, имеющем длинный жизненный цикл и большую вероятность изменения пользовательских требований, способа хранения данных или поддерживаемого оборудования [3].

Чем же он плох? Если кратко, то зависимостью конкретного класса Car от конкретного класса Engine. Представим, что конструктор класса Engine измениться - в этом случае придется менять и Car. Или, к примеру, появиться еще один двигатель. И что бы машина смогла его использовать, опять-таки, понадобиться изменить класс Car. Кроме того, подобная жестко запрограммированная зависимость снижает тестируемость классов - класс Car невозможно протестировать отдельно от Engine или заменить Engine на ложный объект, для симуляции непредвиденных обстоятельств [3].

Что же можно сделать для улучшения кода? Первое - ввести интерфейс IEngine, который будет реализовываться классом Engine.

public interface IEngine {

_МЕЖДУНАРОДНЫЙ НАУЧНЫЙ ЖУРНАЛ «СИМВОЛ НАУКИ» №10-1/2016 ISSN 2410-700Х_

int GetCapacity(); }

public class Engine : IEngine {

public int GetCapacity () {

return 98; }

}

Далее, изменить класс Car, что бы вместо класса Engine в нем использовался интерфейс IEngine. И второе, не менее важное изменение - класс Car не должен создавать двигатель сам, теперь конструктор получает ссылку на объект, реализующий интерфейс IEngine.

public class Car {

private readonly IEngine engine;

public Car(IEngine engine) {

engine = engine; }

public void ShowPower() {

Console.WriteLine("Engine power: {0}", engine.GetSize()); }

}

И последнее, что необходимо сделать - это изменить функцию Main.

class Program {

static void Main() {

IEngine engine = new Engine(); Car car = new Car(engine);

car.ShowPower(); }

}

Получившееся в результате решение легче расширяемо, более тестируемо и является примером реализации паттерна Dependency Injection - зависимость машина-двигатель конфигурируется не внутри класса, а двигатель, созданный вне класса, внедряется в него.

Минус такого решения - потерялась простота создания нового экземпляра класса Car. Представьте, если в программе достаточно много подобных зависимостей, их все придется создавать вручную снова и снова [3].

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

Список использованной литературы: 1. Свободная энциклопедия Википедия [Электронный ресурс]: http:// ru.wikipedia.org/

_МЕЖДУНАРОДНЫЙ НАУЧНЫЙ ЖУРНАЛ «СИМВОЛ НАУКИ» №10-1/2016 ISSN 2410-700Х_

2. Социальное СМИ об IT [Электронный ресурс]: http:// habrahabr.ru/post/131993/

3. [Электронный ресурс]: http://lunarfrog.com/blog/dependency-injection

4. Programming stuff [Электронный ресурс]: http://sergeyteplyakov.blogspot.ru

© Уваров А Н., 2016

УДК 529.194

Щербаков Роман Сергеевич

канд.физ.-мат.наук, ассистент СГУ г.Саратов, РФ E-mail : roman. scherbakoff@yandex.com Бурова Татьяна Геннадиевна доктор физ.-мат.наук, профессор СГУ

г.Саратов, РФ E-mail: burovatg@gmail.com

КВАНТОВО-МЕХАНИЧЕСКИЙ РАСЧЕТ СПЕКТРА РЕЗОНАНСНОГО КОМБИНАЦИОННОГО

РАССЕЯНИЯ ВОДНОГО РАСТВОРА ТРИПТОФАНА

Аннотация

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

Ключевые слова

Квантово-механический расчет, спектр резонансного комбинационного рассеяния.

Изучение спектров резонансного комбинационного рассеяния (РКР) аминокислот является одним из направлений исследования их структуры и физико-химических свойств. Теоретический анализ спектров РКР позволяет дополнить данные, полученные при исследовании спектров ИК и УФ поглощения, а также нерезонансного комбинационного рассеяния, что определяет актуальность настоящей работы.

Таблица 1

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

Спектр РКР водного раствора триптофана, возбуждаемый излучением с длиной волны 220 нм

частота (см-1) отнесение относительная интенсивность

эксперимент наш [4-5] эксперимент наш

[4] [6] [3] [7] расчет [4] [6] [3] [7] расчет

762 757 762 760 768 18 0.8 1.0 0.8 1.0 1.0

880 877 884 879 883 17 0.3 0.2 0.3 0.25 0.21

932 0.9

1016 1006 1016 1011 1033 16 0.9 1.0 1.0 1.0 0.92

1076 1077 15 0.05 0.10

1127 1125 1113 13 - 0.1 0.07

1156 1138 12 0.1 0.08

1238 1232 1241 1239 1240 10 0.25 0.1 0.3 0.2 0.33

1259 1255 9 0.1 0.14

1305 1307 1303 8 0.1 0.1 0.11

1342 1342 1342 1342 0.2 0.3 0.25 0.35

1361 1350 1361 1361 1378 7 0.3 0.4 0.3 0.3 0.32

1462 1460 1461 1450 5 0.2 0.1 0.1 0.09

1496 1495 1498 4 0.2 0.1 0.10

1555 1550 1555 1553 1560 3 1.0 1.0 1.0 0.9 1.0

1575 1578 1580 2 - - 0.05

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