Инвертированное управление что это

Инверсия управления/Inversion of Control

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

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

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

Однако если бы я использовал оконную систему для чего-то похожего, я написал бы что-то, что работает с окном:

Теперь между этими двумя программами большая разница в потоке управления — в частности, в управлении временем, когда вызываются методы process_name и process_quest. В примере с коммандной строкой я контролирую, когда эти методы вызываются, но в примере с оконным приложением нет. Вместо этого я передаю контроль оконной системе (команда Tk.mainloop). Далее она решает, когда вызвать мои методы, основываясь на связях, которые я настроил при создании формы. Управление инвертировано — управляют мной, а не я управляю фреймворком. Это явление и называется инверсией управления (также известно как Принцип Голливуда — «Не звони нам, мы сами позвоним тебе» — Hollywood Principle — «Don’t call us, we’ll call you»).

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

Ральф Джонсон и Брайан Фут.

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

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

Существуют различные способы подключить ваш код для его дальнейшего вызова. В предыдущем примере на ruby, мы вызываем метод bind текстового поля, который принимает имя события и замыкание в качестве аргументов. Всякий раз, когда текстовое поле узнает о событии, оно вызывает наш код из замыкания. Использование таких замыканий очень удобно, но многие языки не поддерживают их.

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

EJB-компоненты являются хорошим примером такого стиля инверсии управления. При разработке сессионного компонента(session bean), вы можете реализовать различные методы, которые вызываются EJB-контейнером в различных точках/состояниях жизненного цикла. Например, у интерфейса SessionBean есть методы ejbRemove, ejbPassivate (сохранен во вторичное хранилище) и ejbActivate (восстановлен из пассивного состояния). Вы не можете управлять вызовом этих методов, только тем, что они делают. Контейнер вызывает нас, а не мы вызываем его.

Примечание перевода, пример:

Это сложные случаи инверсии управления, но вы столкнетесь с этим в гораздо более простых ситуациях. Шаблонный метод является хорошим примером: супер-класс определяет поток управления, субклассы наследуются от него переопределяя методы или реализуя абстрактные методы. Например, в JUnit, код фреймворка вызывает методы setUp и tearDown для вас, чтобы создавать и очищать ваш тест. Происходит вызов, ваш код реагирует — это снова инверсия управления.

Примечание перевода, пример:

В наши дни, в связи с ростом количества IoC-контейнеров, существует некоторая путаница со смыслом инверсии управления. Некоторые люди путают общий принцип с конкретными стилями инверсии управления (такими как внедрение зависимостей), которые эти контейнеры используют. Все это немного запутанно (и иронично), так как IoC-контейнеры, как правило, рассматриваются в качестве конкурента EJB, но EJB использует инверсию управления.

Этимология: Насколько я могу судить, термин инверсии управления впервые появился на свет в работе Джонсона и Фута Designing Reusable Classes, опубликованной в журнале Object-Oriented Programming в 1988 году. Работа является одной из тех, что в возрасте хороши — ее можно прочитать даже спустя пятнадцать лет. Они считают, что они взяли этот термин откуда-то еще, но не могут вспомнить откуда. Затем термин втерся в объектно-ориентированное сообщество и вновь появился в книге Gang of Four. Более красивый синоним «Принцип Голливуда», кажется, берет начало в работе Ричарда Свита в Mesa в 1983 году. В списке целей разработки он пишет: Не звони нам, мы сами позвоним тебе (Закон Голливуда): инструмент должен организовать Тахо, чтобы предупредить его, когда пользователь захочет передать какое-то событие инструменту, вместо того, чтобы принимать модель «запросить у пользователя команду и выполнить ее». Джон Влиссидес пишет колонку о C++, которая несет в себе хорошее объяснение концепции под названием «Принцип Голливуда». (Спасибо Брайану Футу и Ральфу Джонсону за помощь с этимологией).

Источник

Для чего в играх нужна инверсия по оси Y

Инвертированное управление что это. Смотреть фото Инвертированное управление что это. Смотреть картинку Инвертированное управление что это. Картинка про Инвертированное управление что это. Фото Инвертированное управление что это

Все знают, что в настройках практически любой игры есть инверсия. Когда мы тянем контроллер на себя и обзор камеры уходит вверх. Зачем ее добавляют в игры? Многие могут посчитать это каким-то извращением, однако, когда дело касается «леталок», инверсия кажется нам вполне логичной. Почему происходит такая избирательность?

Инвертированное управление что это. Смотреть фото Инвертированное управление что это. Смотреть картинку Инвертированное управление что это. Картинка про Инвертированное управление что это. Фото Инвертированное управление что это

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

Инвертированное управление что это. Смотреть фото Инвертированное управление что это. Смотреть картинку Инвертированное управление что это. Картинка про Инвертированное управление что это. Фото Инвертированное управление что это

Эту картинку наверняка видели все, кто интересовался инверсией. Перевел ее на русский, чтобы было понятней, хотя тут и так все наглядно)

То есть, в данном случае, игрок не сливается воедино с персонажем, а становится этаким «кукловодом». Попробуйте включить инверсию по оси Y в какой-нибудь игре от третьего лица и у вас появится дискомфорт от того, что все поменялось(мышечная память привыкла к стандартам), но при этом мозг не даст сигналов, что это плохо/пиши пропало, наоборот, в глубине души, какая-то частица даже скажет, что это вполне логично.

А как же с шутерами от первого лица? Мы же смотрим на все глазами героя, вживаемся в него, и уж точно мы не будем «марионеткой». Какой мотив для инверсии здесь? Представьте камеру на штативе. Когда мы направляем ее вверх, мы тянем ее назад, и наоборот. То же самое происходит с нашей головой, когда мы смотрим наверх, затылок уходит вниз. Мы смотрим себе под ноги и наклоняемся вперед. Эти действия кто-то тоже может воплотить с мышью. Но на это есть контраргумент.

Инвертированное управление что это. Смотреть фото Инвертированное управление что это. Смотреть картинку Инвертированное управление что это. Картинка про Инвертированное управление что это. Фото Инвертированное управление что это

А это уже взгляд более «традиционного» игрока.

Источник

Как использовать Инверсию Управления в JavaScript и в Reactjs для упрощения работы с кодом

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

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

Что именно делает код кошмаром для использования и поддержки? Есть несколько аспектов, которые могут сделать ваш код проблемным:

В итоге все страдают. Стоит заметить что реализация конечной программы является важнейшей частью разработки. Но было бы отлично если бы мы больше думали о реализации наших абстракций (читайте про «AHA programming»). Существует ли способ, который позволит нам уменьшить проблемы с повторно используемым кодом, и, при этом, все еще пожинать преимущества использования абстракций?

Инверсия управления

Инверсия управления это принцип который действительно упрощает создание и использование абстракций. Вот что говорит об этом Википедия:

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

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

Что такое Инверсия Управления в коде?

Для начала, вот очень надуманный пример:

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

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

В целом, это довольно простая абстракция. Но ее можно упростить. Часто бывает так, что абстракцию, в которую добавляли новый функционал, можно было бы сильно упростить для тех вариантов использования которые она фактически и поддерживает. К сожалению, как только абстракция начинает что-то поддерживать (например, выполнение < filterZero: true, filterUndefined: false >), мы боимся удалять эту функциональность из-за того что это может сломать код который на нее полагается.

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

Окей, давайте теперь напишем более продуманную абстракцию к этой функции и применим метод инверсии управления для поддержки всех нужных нам вариантов использования:

Отлично! Вышло намного проще. Мы только что перевернули управление функцией, передав ответственность за принятие решения о том, какой элемент попадает в новый массив, с функции filter на функцию, вызывающую функцию фильтра. Заметьте, что функция filter все еще является полезной абстракцией сама по себе, но теперь она гораздо более гибкая.

Но была ли предыдущая версия этой абстракции настолько уж плохой? Возможно, нет. Но так как мы перевернули управление, теперь мы можем поддерживать гораздо более уникальные варианты использования:

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

Плохой API?

Одна из самых распространенных жалоб, которую я слышу от людей, касательно API-интерфейсов в которых применяется инверсия управления это: «Да, но теперь этим сложнее пользоваться, чем раньше». Возьмите этот пример:

Да, один из вариантов явно проще в использовании, чем другой. Но одним из преимуществ инверсии управления является то что вы можете использовать API в котором применяется инверсия управления для повторной реализации вашего старого API. Обычно это довольно просто. К примеру:

Круто, да? Таким образом мы можем создавать абстракции поверх API в котором применяется инверсия управления, и тем самым создавать более простой API. А если в нашем «более простом» API недостаточно вариантов использования, тогда наши пользователи могут применить те же самые строительные блоки, которые мы использовали для создания нашего высокоуровневого API, чтобы разрабатывать решения для более сложных задач. Им не нужно просить нас добавить новую функцию в filterWithOptions и ждать, пока она будет реализована. У них уже есть инструменты при помощи которых они могут самостоятельно разрабатывать нужный им дополнительный функционал.

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

Примеры из реальной жизни

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

Вот два моих любимых паттерна, которые демонструют это «Compound Components» и «State Reducers». Ниже идут краткие примеры того, как можно применять эти паттерны.

Составные Компоненты (Compound Components)

Когда вы думаете о том, как создать хороший API для людей, которые пытаются сделать что-то немного по-другому, вместо того чтобы тянуться к if оператору, попробуйте инвертировать управление. Что если мы передадим ответственность за визуализацию меню на пользователя? Используем одну из самых сильных сторон Реакта:

Важный момент, на который следует обратить внимание — здесь нет состояния ( state ) видимого пользователю компонентов. Состояние неявно разделяется между этими компонентами. Это основная ценность паттерна составных компонентов. Используя эту возможность, мы предоставили некоторый контроль над рендерингом пользователю наших компонентов, и теперь добавление дополнительной строки (или чего-то еще) является простым и интуитивно понятным действием. Никакой дополнительной документации, никаких дополнительных функций, никакого лишнего кода или тестов. Все в выигрыше.

Вы можете почитать больше об этом паттерне здесь. Спасибо Райану Флоренсу, который научил меня этому.

Редюсер Состояния (State Reducer)

Вместо этого я сделал API таким, чтобы пользователи сами могли контролировать как происходят изменения состояния. Думайте о состоянии редюсера ( state reducer ) как о состояний функции, которая вызывается каждый раз, когда изменяется состояние компонента, и дает разработчику приложения возможность влиять на изменение состояния, которое должно произойти.

Пример использования библиотеки Downshift таким образом чтобы она не закрывала меню после того как пользователь нажал на выбранный элемент:

После того как мы добавили этот проп, мы стали получать НАМНОГО меньше запросов на добавление новых настроек для этого компонента. Компонент стал более гибким, и разработчикам стало проще настраивать его так как нужно именно им.

Рендер-пропсы (Render Props)

Стоит упомянуть паттерн «render props». Этот паттерн является идеальным примером использования инверсии управления, но он нам особо больше и не нужен. Подробнее об этом здесь: why we don’t need Render Props as much anymore.

Предупреждение

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

Вернемся к нашему надуманному примеру:

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

Выводы

Надеюсь что статья была полезной для вас. Я показал как можно применять концепцию Инверсии Управления в Реакте. Эта концепция, конечно же, применима не только к React (как мы видели на примере функции filter ). В следующий раз когда вы заметите что добавляете очередной оператор if в функцию coreBusinessLogic вашего приложения, подумайте, как вы можете инвертировать управление и перенести логику туда, где она используется (или, если она используется в нескольких местах, вы можете создать более специализированную абстракцию для этого конкретного случая).

Если хотите, можете поиграть с примером из статьи на CodeSandbox.

Удачи и спасибо за внимание!

ПС. Если вам понравилась эта статья, вам возможно понравится это выступление: youtube Kent C Dodds — Simply React

Источник

Инвертируете ли вы мышь в 3D-играх? (Исследую что естественнее…)

Комментарии 31

Инвертированное управление что это. Смотреть фото Инвертированное управление что это. Смотреть картинку Инвертированное управление что это. Картинка про Инвертированное управление что это. Фото Инвертированное управление что это

Я инвертирую; в первую очередь в силу привычки.

Но я нахожу и достаточно объективные причины для инвертации: попробуйте стоя вытягивать вперёд руку — постепенно вы уткнётесь взглядом в землю, а потом и вовсе на неё, землю, повалитесь. Перемещение же рукой мыши вперёд, по-умолчанию заставляет нас смотреть на звёзды.

Ещё, катание мыши по столу можно сравнить с использованием рычага с «точкой сборки» на полу (не в небе же), а рычаг это тоже хорошо известный человеку «прибор».

Вот такой аргумент в пользу инвертации: десятки лет взаимодействия с простейшими законами физики.

Может у кого есть другие обоснования на сей счёт?

Инвертированное управление что это. Смотреть фото Инвертированное управление что это. Смотреть картинку Инвертированное управление что это. Картинка про Инвертированное управление что это. Фото Инвертированное управление что это

Инвертированное управление что это. Смотреть фото Инвертированное управление что это. Смотреть картинку Инвертированное управление что это. Картинка про Инвертированное управление что это. Фото Инвертированное управление что это

Че-то вы тут наворотили доводов, громоздко все и сложно.
Соглашусь только с первым предложением, а именно, да: сила привычки, кто как изначально научился, тот так и играет.

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

Мое объяснение проще: мышь — это манипулятор, и нормальные люди перемещают мышь так, чтобы она в точности повторяла движения указателя на экране. А перемещение рукой мыши вперед значит перемещение указателя вверх, не так ли?! Или вы скажете, что в ОС тоже мышь инвертируете?

То есть мышь изначально предназначена, чтобы перемещать указатель, причем:
перемещаем мышь влево — указатель смещается влево,
перемещаем мышь вправо — указатель смещается вправо,
перемещаем мышь назад — указатель смещается вниз,
перемещаем мышь вперед — указатель смещается вверх,

Если бы мышь можно было бы перещать вверх-вниз, а не вперед-назад, сабжа бы не было, вряд ли, зачем тогда нужен был бы инверт? Игроки в Wii, скажите, на этой хреновине есть инверт манипулятора?)))

Можно и по-другому зайти. Дорожные знаки видели? Ну так вот, там нарисованная стрелка вверх вовсе не означает, что Вам надо взлетать ))))

Источник

Что такое инверсия контроля?

Инверсия управления (IoC) может сбивать с толку, когда встречается впервые.

30 ответов

Шаблоны Inversion of Control (IoC) и Dependency Injection (DI) предназначены для удаления зависимостей из вашего кода.

Например, предположим, что в вашем приложении есть компонент текстового редактора, и вы хотите обеспечить проверку орфографии. Ваш стандартный код будет выглядеть примерно так:

Во втором примере кода мы создаем абстракцию, имея класс зависимости SpellChecker в сигнатуре конструктора TextEditor (не инициализируя зависимость в классе). Это позволяет нам вызвать зависимость, а затем передать ее классу TextEditor следующим образом:

Например, в меню старой школы у вас может быть:

Тем самым контролируя поток взаимодействия с пользователем.

Вместо этого в программе с графическим интерфейсом пользователя мы говорим:

По сути, все с циклом событий, обратными вызовами или триггерами выполнения попадает в эту категорию.

Что такое инверсия контроля?

Если вы выполните эти два простых шага, вы выполнили инверсию управления:

Для каждого из этих шагов существует несколько возможных методов в зависимости от технологии / языка, которые вы используете для своей реализации.

Когда вы используете настольный компьютер, вы подчиняетесь (или, скажем, контролируете). Вы должны сидеть перед экраном и смотреть на него. Использование клавиатуры для ввода и использование мыши для навигации. А плохо написанное программное обеспечение может еще больше вас поработить. Если вы замените рабочий стол ноутбуком, то управление у вас несколько перевернулось. Вы можете легко взять его и передвигаться. Так что теперь вы можете контролировать, где вы находитесь со своим компьютером, вместо того, чтобы управлять им.

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

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

Хотя рабочие передают управление проектом на высшем уровне менеджерам (фреймворку). Но хорошо, когда вам помогают профессионалы. Это действительно концепция IoC.

Современные веб-приложения с архитектурой MVC зависят от инфраструктуры, которая выполняет маршрутизацию URL-адресов и устанавливает контроллеры для вызова инфраструктуры.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *