Реактивная функция: 14 Реактивная функция жизненного цикла

Содержание

Вступление в Реактивное Программирование, которое вы пропустили / Хабр

Ну что ж, вы решили выучить новую вещь, которая называется Реактивное программирование (Reactive Programming), а в частности — его имплементацию в виде Rx, Bacon.js, RAC или чего-то другого.

Обучение — сложный процесс, который становится еще труднее, когда нету подходящего материала. И в начале моего обучения, я пытался найти какие-то туториалы. Но все что я находил были частичные гайди, которые носили поверхностных характер и не давали целостного представления о построении архитектуры. А документация по библиотекам не особо помогла при понимании некоторых функций:

Rx.Observable.prototype.flatMapLatest(selector, [thisArg])

Projects each element of an observable sequence into a new sequence of observable sequences by incorporating the element’s index and then transforms an observable sequence of observable sequences into an observable sequence producing values only from the most recent observable sequence.

Святая Корова!

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

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

В интернете существует много плохих объяснений и определений реактивного программирования. Например Википедия как всегда все обобщает и теоретизирует, а Stackoverflow содержит каноничные ответы, которые не подходят новичку. Reactive Manifesto звучит, как одна из тех вещей, которые нужно показывать своему проектному менеджеру или бизнес аналитику своей компании. А Rx terminology «Rx = Observables + LINQ + Schedulers» настолько тяжел и майкрософтный, что большинству из нас остается только возмущаться. Слоганы вроде «реактивный» и «распространение изменений» не объясняют ничего конкретного, что отличало б типичный подход MV*, который уже встроен в ваш язык. Конечно же представления из моего фреймворка реагируют на модели. Конечно же распространение изменений. Если б это было не так — то мы б не увидели работу программы.

Ну что ж, давайте расставим точки над i.

Реактивное программирование — это программирование с асинхронными потоками(streams) данных.

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

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

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

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

Поток — это последовательность, состоящая из постоянных событий, отсортированных по времени

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

Мы получаем эти cгенерированные события асинхронно, всегда. Согласно идеологии реактивного программирования существуют три вида функций: те, которые должны выполняться, когда некоторые конкретные данные будут отправлены, функции обработки ошибок и другие функции с сигналами о завершении работы программы. Иногда последнее два пункта можно опустить и сосредоточится на определении функций для обработки значений. Слушать(listening) поток означает подписаться(subscribing) на него. То есть функции, которые мы определили это наблюдатели(observers). А поток является субъектом который наблюдают. Такой подход называется Observer Design Pattern.

Альтернативным способом представить вышеупомянутую диаграмму является ASCII графика, которую мы будем использовать в некоторых разделах этого туториала:
--a---b-c---d---X---|->

a, b, c, d are emitted values
X is an error
| is the 'completed' signal
---> is the timeline

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

Первое что мы сделаем — добавим счетчик, который будет индикатором нажатий кнопки. В большинстве Реактивных библиотек каждый поток имеет много встроенных функций, таких как объединение, фильтр, сканер и так дальше. Когда вы вызываете одну из этих функций, таких как clickStream.map(f), она возвращает новый поток, который базируется на родительском(на clickStream). Дочерний поток никаким образом не затрагивает и не модифицирует своего родителя. Это свойство называется постоянностью(immutability) и является неотъемлемой частью реактивных потоков, так само как блинчики нельзя себе представить без сиропа. Это разрешает нам объединять функции(например — clickStream.map(f).scan(g)):

clickStream: ---c----c--c----c------c-->
               vvvvv map(c becomes 1) vvvv
               ---1----1--1----1------1-->
               vvvvvvvvv scan(+) vvvvvvvvv
counterStream: ---1----2--3----4------5-->

Функция map(f) создает новый поток, в котором с помощью функции f заменяться каждое новое событие. В нашем случае мы привязываем единицу к каждом нажатию на кнопку. Функция scan(g) агрегирует все предыдущие значение в потоке, возвращая значение x = g(accumulated, current). После этого counterStream посылает общее количество нажатий.

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

То-есть, в Реактивном программирование все очень просто. По сути логика сосредоточена в 4 строчках кода
. Но давайте не будем обращать внимание на код, пока что. Размышление над диаграмой — лучший способ для понимания и построение потоков, без разницы, являетесь ли вы экспертом или только начинаете.


Серые прямоугольники являются функциями трансформации одного потока в другой. Первое, что мы сделали — аккумулировали клики в список. Всякий раз, когда 250 миллисекунд задержки события проходят (вот почему buffer(stream.throttle(250ms)), генерируется событие. Не переживайте насчет понимания деталей этого момента. Мы только разбираемся с Реактивностью. Результатом является поток списка, где к каждому элементу была применена функция map(), чтобы присоединить к каждому списку его длину. И наконец мы игнорируем число 1, используя функцию filter(x >= 2). Это все — всего 3 операции для того что бы создать наш целевой поток. Мы можем подписать на него листенер, который будет реагировать в точности так, как мы захотим.

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

Ультразвуковая постпрандиальная проба. — Клиника на Ленинском

ОЦЕНКА ФУНКЦИОНАЛЬНОЙ АКТИВНОСТИ ПОДЖЕЛУДОЧНОЙ ЖЕЛЕЗЫ.

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

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

Оценка состояния поджелудочной железы входит в протокол УЗИ брюшной полости. При стандартном УЗИ часто получаем заключение – «реактивные изменения поджелудочной железы», «реактивный панкреатит», «реактивное увеличение поджелудочной железы» и тд.

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

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

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

Сначала врач ультразвуковой диагностики выполняет исследование поджелудочной железы натощак, после 6-8 часов голода. Оцениваются ее размер, контуры, структура, кровоток.

И повторяет исследование ПЖ через 1,5-2 часа после пищевой нагрузки, содержащей 20 гр жира – это 100гр 20% сметаны или 20 гр сливочного масла или 2 желтка , которые являются естественными стимуляторами панкреатической секреции.

Поджелудочная железа опять оценивается по тем же параметрам. На основании полученных данных врач делает вывод о функциональных возможностях органа, что это:

  • нормальная не измененная ПЖ
  • реактивный панкреатит (реактивное состояние)
  • латентный панкреатит
  • хронический панкреатит.

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

В Клинике на Ленинском постпрандиальную пробу проводят специалисты УЗИ:

Роговец Оксана Владимировна
Медведева Наталья Владиславовна

Запись по телефону +7(495)668-09-86

 

Защитные механизмы личности

Впервые термин «защитный механизм» ввел Зигмунд Фрейд.

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

К основным защитным механизмам относятся: вытеснение, проекция, замещение, рационализация, реактивное образование, регрессия, сублимация, отрицание.

  1. Вытеснение.

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

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

  1. Проекция.

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

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

  1. Замещение.

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

  1. Рационализация.

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

  1. Реактивное образование.

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

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

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

  1. Регрессия.

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

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

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

  1. Сублимация.

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

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

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

  1. Отрицание

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

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

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

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

1) защитные механизмы проявляются на бессознательном уровне, т.е. человек не осознает, что использует механизмы защиты;

2) защитные механизмы не проявляются изолированно, т.е. личностью обычно используется 1-2 механизма защиты;

3) защитные механизмы охраняют человека от захлестывающей его тревоги, напряженности, предотвращают дезорганизацию поведения и помогают сохранить целостность личности.

4) осведомленность человека о существовании у него психологических защит помогает ему лучше понимать и принимать себя.

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

 

Список использованной литературы:

  1. Мельник С.Н., Психология личности
  2. С. А. Зелинский Защитные механизмы психики. Характеристики основных защит
  3. Чумакова Елена Викторовна «Психологическая защита личности в системе детско-родительского взаимодействия»
  4. Белов В.Г., Бирюкова Г.М., Федоренко В.В. Психологическая защита и ее роль в процессе формирования адаптационной системы человека.
  5. С.Л. Богомаз Психологическая защита личности: методология, механизмы, инструментарий.

 

Материал подготовила психолог Черных И.Д.,

медико-психологическое отделение.

 

Высокочувствительный С-реактивный белок (hsCRP)

С-реактивный белок человека (СРБ) является одним из так называемых белков острой фазы. Его концентрация в крови быстро увеличивается в ответ на воспаление. СРБ представляет собой 224 остатка белка с молекулярной массой мономера приблизительно 25 кДа и pI 6,4 (1-4). Его относят к пентраксинам, эволюционно консервативному семейству белков, характеризующемуся кальций-зависимым связыванием лиганда и радиальной симметрией пяти мономеров, образующих кольцо вокруг центральной поры (5).
Точная функция СРБ в естественных условиях еще не полностью ясна. Было показано, что СРБ участвует в воспалительных процессах, а также в процессах врожденного иммунитета. Важная биологическая активность СРБ определяется его способностью связываться с различными лигандами, такими как: поврежденные клеточные мембраны, апоптозные клетки и фибронектин, с наибольшим сродством к остаткам фосфохолина. Когда СРБ связан с лигандом, это может быть распознано компонентом комплемента C1q, что приводит к активации классического пути комплемента. С другой стороны, посредством взаимодействия с фактором комплемента H, CRP регулирует альтернативный путь комплемента (6).

СРБ в диагностике

В клинической практике С-реактивный белок используют в качестве основного, хотя и довольно неспецифичного, маркера воспаления. Как правило, у здоровых людей уровень СРБ обычно составляет менее 5 мг/л. При патологии концентрация СРБ имеет огромный 10 000-кратный динамический диапазон (приблизительно 0,05–500 мг/л) (7). Самые высокие уровни СРБ (выше 30 мг/л) наблюдаются при бактериальных инфекциях, таких как септический артрит, менингит и пневмония.
В 2003 году Центры по контролю и профилактике заболеваний (CDC) и Американская кардиологическая ассоциация (AHA) опубликовали заявление, в котором CRP был назван маркером воспаления, наиболее подходящим для использования в современной клинической практике для оценки риска сердечно-сосудистых заболеваний (8). Многие эпидемиологические исследования показали, что СРБ является надежным независимым предиктором будущих сердечно-сосудистых событий, включая инфаркт миокарда, ишемический инсульт, заболевание периферических сосудов и внезапную сердечную смерть без каких-либо признаков сердечно-сосудистых заболеваний (согласно обзору Clearfield (9)). Рекомендации CDC/AHA поддерживают использование CRP в первичной профилактике и устанавливают пороговые значения в соответствии с категориями относительного риска: низкий риск (<1,0 мг/л), средний риск (1,0-3,0 мг/л) и высокий риск (> 3,0 мг/л). Именно почему современные высокочувствительные наборы для определения СРБ (hsCRP) направлены на распознавание уровней СРБ в нанограммах на миллилитр (нг/мл).

Реагенты для разработки hsCRP тестов

Моноклональные антитела Хайтест были использованы в новых иммунометрических аналитических системах, которые достигают превосходной чувствительности с линейным диапазоном обнаружения от 0,025 мг/л до 2,5 мг/л в магнитном биосенсорном анализе (10), и от 0,01 мг/л до 50 мг/л в иммунохемилюминометрическом анализе (11). В обоих случаях предел обнаружения составлял 0,004 мг/л. Предел обнаружения 0,0011 мг/л был достигнут в твердофазном сэндвич-флуоресцентном иммуноанализе с использованием нанокристаллов (12). Наши лучшие пары C2сс–C6сс и C5–СРБ135 и несколько других обеспечивают 10 000-кратную линейность в экспериментальных иммунофлуориметрических анализах. Наши антитела могут быть использованы для разработки высокочувствительных анализов для детекции СРБ для различных диагностических платформ. В дополнение к моноклональным антителам, мы также предоставляем очищенный нативный С-реактивный белок.

Приложения

В нативной молекуле СРБ каждый протомер имеет двух-координированные ионы Ca2+ (13). Хайтест предлагает моноклональные антитела к СРБ, которые чувствительны или нечувствительны к присутствию Ca2+ в растворе. Некоторые из наших антител распознают антиген только в присутствии Ca2+ (клоны C3, C4). Большинство моноклонов Хайтест не зависят от присутствия Ca2+ в сэндвич-иммуноанализе и способны эффективно распознавать антиген даже в присутствии EDTA в тестируемом образце (клоны C1, C2, С2сс, C5, C6, С6сс, С7, CRP11, CRP30, CRP30cc, CRP36, CRP103, CRP135, CRP169). Все антитела к СРБ компании Хайтест тестировались в различных иммунологических приложениях.
Ссылки на литературу:

Поиск ссылок о С-реактивном белке в PubMed.
Посмотреть все ссылки о CRP.

Продукция:

Мозговая деятельность и Человеческий мозг, Области деятельности мозга

Какова функция мозга?

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

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

Что такое когнитивные функции?

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

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

Какие функции являются когнитивными?

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

ВНИМАНИЕ: Внимание — это очень сложный умственный процесс, охватывающий множество других процессов, которому трудно дать короткое определение или отнести к какой-то определённой анатомической структуре. Другими словами, внимание — это когнитивная способность, с помощью которой мы выбираем среди внешних (запахи, звуки, образы) и внутренних (мысли, эмоции) стимулов те, которые нам полезны и необходимы для реализации умственной или двигательной активности. Это совокупность различающихся по сложности процессов, которые позволяют нам правильно выполнять другие когнитивные функции. Согласно иерархической модели Солберга и Матиера (Sohlberg & Mateer, 1987; Sohlberg & Mateer, 1989), существуют различные виды внимания в зависимости от степени сложности:

ФОКУСИРОВАННОЕ ВНИМАНИЕ: состояние готовности, бдительность. Способность ответить на стимул.

ПОСТОЯННОЕ ИЛИ НЕОСЛАБНОЕ ВНИМАНИЕ: способность поддерживать внимание в течение не менее трёх минут. Обычно мы называем это концентрацией или сосредоточенностью. Например, мы очень сосредоточены при чтении книги.

ВЫБОРОЧНОЕ ИЛИ СЕЛЕКТИВНОЕ ВНИМАНИЕ: способность удерживать внимание на задаче, не отвлекаясь на факторы окружающей среды, например, шум. Селективное внимание позволяет нам читать книгу под звуки музыки или шум стиральной машины.

ЧЕРЕДУЮЩЕЕСЯ ВНИМАНИЕ: умственная способность быстро переключать внимание с одной задачи на другую. Например, если при чтении мы слышим песню, которая нам нравится, возможно, мы прекратим читать и начнём петь или слушать эту песню, после чего быстро сможем вернуться к чтению книги.

РАЗДЕЛЁННОЕ ВНИМАНИЕ: способность выполнять несколько задач в одно и то же время, т.е. заниматься двумя делами одновременно. Например, когда мы беседуем с другом в баре и одновременно пишем в whatsapp, или когда готовим и при этом разговариваем по телефону (смотрим телевизор, слушаем музыку и т.д.)

Одной единственной анатомической структуры, отвечающей за внимание, не существует, поскольку в эти процессы вовлечён ряд систем. Согласно модели Познера и Петерсена (Познер и Петерсен, 1990), различают три системы внимания:

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

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

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

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

1- ВРЕМЕННОЙ КРИТЕРИЙ:

Кратковременная память:

— Немедленная память

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

Долгосрочная память

2 -ПО ЗАДЕЙСТВОВАННЫМ ОБЛАСТЯМ МОЗГА:

Декларативная (эксплицитная) память: воспоминания, которые можно пробудить осознанно.

— Эпизодическая — это автобиографическая память, благодаря которой мы можем вспоминать наше прошлое. Например, куда вы ездили в отпуск в прошлом году, когда закончили учёбу, когда поженились или вышли замуж.

— Семантическая: этот вид памяти относится к тому, что мы выучили, а также к общим знаниям об окружающем нас мире. Какой город является столицей Франции? Что такое квадратный корень?

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

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

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

ИСПОЛНИТЕЛЬНЫЕ ФУНКЦИИ: являются самыми сложными когнитивными функциями. Несмотря на существование различных определений исполнительной функции, почти все они сводятся к контролю когнитивности и регулированию мышления и поведения при помощи различных взаимосвязанных процессов. Речь идет о совокупности таких сложных способностей как направление внимания, планирование, программирование, регулирование и проверка преднамеренного поведения. Находятся в префронтальной коре мозга. М. Лезак группирует эти функции следущим образом:

1- Постановка целей:

— Самосознание

— Форма восприятия нашей связи с окружающим миром

2 -Планирование этапов и стратегий для достижения целей:

— Способность абстрагироваться

— Когнитивная гибкость, т.е. способность к альтернативному мышлению

— Способность оценить различные варианты поведения и выбрать один из них

3- Способности, связанные с исполнением действия:

— Способность упорядоченно и комплексно начинать, поддерживать и чередовать действия

4- Способности эффективно выполнять действия или следовать линии поведения:

— Контроль времени

— Использование обратной связи

— Саморегулирование поведения

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

РЕЧЬ: речь — это символическая система коммуникации людей посредством языков. Речь важна не только для нашего общения с другими людьми, но и для структурирования мышления. В обработке речи участвуют различные области головного мозга, взамодействующие между собой посредством различных функциональных систем, главным образом, в левом полушарии. Речь идёт прежде всего о двух корковых областях, главным образом, левого полушария, отвечающих за выражение и принятие речи.

1- ОБЛАСТЬ ВЫРАЖЕНИЯ РЕЧИ: включает в себя различные области коры головного мозга:

— Префронтальная область: вовлечена в мотивационные процессы в языке. Это там, где начинается коммуникация — как вербальная, так и письменная (связанная с исполнительными функциями).

— Центр Брока: расположен в левой лобной доле, связан с воспроизведением и обработкой разговорной речи.

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

2- ОБЛАСТЬ ПРИНЯТИЯ РЕЧИ: в неё входят:

— Затылочная доля: позволяет идентифицировать лингвистические изображения.

— Теменная доля: ответственна за объединение зрительных и слуховых стимулов.

— Левая височная доля: отвечает за процессы синтеза звуков речи, а также их понимания. Она находится: в области Хешла (первичная звуковая область; принимает звуки для того, чтобы кодировать их в мультимодальной области) и Область Вернике (связана с пониманием речи; наделяет смыслом воспринимаемые звуки).

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

ФУНКЦИИ ЗРИТЕЛЬНОГО ВОСПРИЯТИЯ И ЗРИТЕЛЬНО-ПРОСТРАНСТВЕННЫЕ ФУНКЦИИ: к ним относят те функции, которые позволяют нам распознавать и различать стимулы. Они помогают нам трактовать, объяснять и связывать то, что мы видим, со знакомыми нам категориями и, таким образом, запоминать. Корректная работа данных функций позволяет нам, например, узнавать лица родных и друзей, или отличать расчёску от ключей или шляпы.

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

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

Зачем мы пользуемся функциями мозга?

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

  • Является ли приготовление пищи хорошим упражнением для мозга? Когда вы готовите, вам нужно следить за несколькими кастрюлями и сковородками одновременно, при этом вы ещё думаете о гостях и вспоминаете рецепт блюда.
  • Какие функции мозга должны активироваться для успешного руководства совещанием? Руководство рабочим совещанием или семейным советом — сложная задача, при которой необходимо, чтобы ваш мозг активировал определённые нейронные сети и функции, связанные с вниманием, концентрацией, способностью внимательно слушать, скоростью ответа и т.д.
  • Запуск воздушного змея? Большинство людей считает, что расслабление — это естесственный процесс, однако без основных когнитивных способностей расслабиться было бы невозможно.
  • Вождение автомобиля? Даже если вы прекрасный водитель, для того, чтобы добраться до пункта назначения, нужны навыки, концентрация и широкая гамма когнитивных способностей
  • Встретиться с другом? Жизнь была бы очень скучной и одинокой, если бы у нас не было когнитивных способностей, позволяющих нам знакомиться и общаться с людьми, которые нас окружают.

Referencias: Finisguerra, A. Borgatti, R., Urgesi, C. (2019). Non-invasive Brain Stimulation for the Rehabilitation of Children and Adolescents With Neurodevelopmental Disorders: A systematic Review. Front Psychol. vol. 10 (135). • Posner, M. I. y Petersen, S. E. (1990). The attention system of the human brain. Annual Review of Neuroscience, 13, 25-42. • Sohlberg, M. M. y Mateer, C. A. (1987). Effectiveness of an attention-training program. Journal of Clinical and Experimental Neuropsychology, 9 (2), 117-130. •Sohlberg, M. M. y Mateer, C.A. (1989) Introduction to Cognitive Rehabilitation. New York: Guilford.

Корутины 1.5 в Kotlin: GlobalScope отмечен как «требующий внимания», улучшенный Channels API и многое другое

Libraries

Read this post in other languages:
English, Français, 日本語, 한국어, Deutsch, 简体中文

Соавтор: Светлана Исакова

Представляем корутины 1.5.0! Вот что реализовано в новой версии.

  • Улучшенный Channels API. Помимо новых правил именования для функций библиотеки, были реализованы неостанавливаемые функции trySend и tryReceive, ставшие улучшенной альтернативой для offer и poll.

Кроме того, в этой статье вы найдете рекомендации по миграции на новую версию.

Начните использовать корутины 1.5.0

Теперь класс GlobalScope отмечен аннотацией @DelicateCoroutinesApi. Начиная с этой версии, для использования GlobalScope его необходимо явным образом включить, используя аннотацию @OptIn(DelicateCoroutinesApi::class).

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

Глобальная область CoroutineScope не связана ни с каким заданием. Такой вариант используется для запуска корутин верхнего уровня, которые работают в течение всего срока жизни приложения. Активные корутины, запущенные в GlobalScope, не препятствуют остановке процесса. Они похожи на потоки-демоны в Java.

При использовании API GlobalScope нужно быть очень внимательным, потому что можно легко организовать утечку ресурсов или памяти. Корутины, запущенные в GlobalScope, не подчиняются принципу структурированного параллелизма. Если они зависают или тормозят (например, из-за низкой пропускной способности сети), то все равно продолжают работать, потребляя ресурсы. Возьмем, например, следующий код:

fun loadConfiguration() {
GlobalScope.launch {
val config = fetchConfigFromServer() // network request
updateConfiguration(config)
}
}

Вызов loadConfiguration создает корутину в GlobalScope, которая работает в фоновом режиме, и не заданы никакие условия ее отмены или ожидания ее завершения. Если пропускная способность сети низкая, она просто ожидает в фоновом режиме, потребляя ресурсы. При повторных вызовах loadConfiguration потребление ресурсов будет постоянно расти.

Возможная замена

Во многих случаях использования GlobalScope следует избегать, а содержащую его операцию следуют отметить как suspend, например:

suspend fun loadConfiguration() {
    val config = fetchConfigFromServer() // network request
    updateConfiguration(config)
}

Если вы используете GlobalScope.launch для запуска нескольких параллельных операций, их следует сгруппировать, используя coroutineScope:

// concurrently load configuration and data
suspend fun loadConfigurationAndData() {
    coroutineScope {
        launch { loadConfiguration() }
        launch { loadData() }
    }
}

При запуске параллельной операции из неостанавливаемого контекста в коде верхнего уровня вместо GlobalScope следует использовать правильно ограниченный экземпляр CoroutineScope.

Случаи оправданного использования

Существует ряд ситуаций, когда использование GlobalScope оправданно и безопасно, например, фоновые процессы верхнего уровня, которые должны работать в течение всего срока жизни приложения. Поэтому, начиная с этой версии, для использования GlobalScope его необходимо явным образом включить, используя аннотацию @OptIn(DelicateCoroutinesApi::class) как показано ниже:

// A global coroutine to log statistics every second,
// must be always active
@OptIn(DelicateCoroutinesApi::class)
val globalScopeReporter = GlobalScope.launch {
    while (true) {
        delay(1000)
        logStatistics()
    }
}

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

В новой версии мы добавили аннотацию CoroutinesTimeout, которая позволяет запускать тесты в отдельном потоке, отключать их после истечения отведенного времени и прерывать поток. CoroutinesTimeout уже был доступен для JUnit 4. В этой версии мы добавили интеграцию с JUnit 5.

Чтобы использовать новую аннотацию, добавьте в проект новую зависимость:

dependencies {
  …
  testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-debug:$coroutinesVersion")
}

Вот простой пример использования нового CoroutinesTimeout для тестирования:

import kotlinx.coroutines.debug.junit5.CoroutinesTimeout
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.junit.Test

@CoroutinesTimeout(100)
class CoroutinesTimeoutSimpleTest {

     @CoroutinesTimeout(300)
     @Test
     fun firstTest() {
         runBlocking {
             delay(200)  // succeeds
         }
     }

     @Test
     fun secondTest() {
         runBlocking {
             delay(200)  // fails
         }
     }
 }

В этом примере тайм-аут корутин определяется на уровне класса, конкретно для firstTest. Для аннотированного теста тайм-аут не учитывается, поскольку аннотация функции переопределяет функцию класса. secondTest использует аннотацию на уровне класса, поэтому он завершается при превышении лимита времени.

Аннотация объявляется следующим образом:

package kotlinx.coroutines.debug.junit5

public annotation class CoroutinesTimeout(
    val testTimeoutMs: Long,
    val cancelOnTimeout: Boolean = false
)

Первый параметр, testTimeoutMs, определяет продолжительность времени ожидания в миллисекундах. Второй параметр, cancelOnTimeout, определяет, нужно ли отменить все выполняемые корутины по истечении этого времени. Если для него задано значение true, все корутины будут автоматически отменены.

При использовании аннотации CoroutinesTimeout автоматически включается отладчик корутин, который делает дамп всех корутин в момент таймаута. Дамп содержит трассировки стека создания корутин. Если нужно отменить трассировку стека, чтобы ускорить выполнение тестов, можно использовать напрямую CoroutinesTimeoutExtension — это позволяет сделать соответствующие настройки.

Мы благодарим Абхиджита Саркара, который создал экспериментальный образец CoroutinesTimeout для JUnit 5. Идея была реализована в новой аннотации CoroutinesTimeout, которая и добавлена в версию 1.5.

Каналы — важные примитивы коммуникации, которые позволяют различным корутинам обмениваться данными. В этой версии мы немного обновили Channels API, предложив улучшенные альтернативы для функций offer и poll, которые часто создавали проблемы при использовании. Заодно мы разработали новые последовательные правила именования для останавливаемых и неостанавливаемых методов.

Новые правила именования

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

  • имена обычных останавливаемых методов остаются без изменений — например, send, receive;
  • все имена соответствующих неостанавливаемых методов с инкапсуляцией ошибок получают префикс «try»: trySend и tryReceive вместо прежних offer и poll;
  • имена новых останавливаемых методов с инкапсуляцией ошибок получают суффикс «Catching».

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

Функции

Try: неостанавливаемые аналоги для send и receive

Одна корутина может отправлять информацию в канал, а другая может ее оттуда получать. Обе функции send и receive — останавливаемые. send останавливает корутину, если канал полон и не может принять новый элемент, а receive останавливает свою корутину, если в канале нет возвращаемых элементов:

import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() = runBlocking<Unit> {
    val channel = Channel<String>()
    launch {
        // Suspends until the element can be sent
        println("Sending...")
        channel.send("Element")
     }
     // Suspends until the element can be received
     println("Receiving...")
     println(channel.receive())
}

У этих функций есть неостанавливаемые аналоги, используемые в синхронном коде: offer и poll. Теперь вместо них появились trySend и tryReceive, а поддержка прежних функций прекращается. Ниже мы подробнее расскажем о причинах таких изменений.

offer и poll должны делать то же, что и send и receive, но без остановки. Звучит просто и успешно работает, когда можно отправить или получить элемент. А вот когда происходит ошибка, все усложняется. send и receive останавливают соответствующие корутины до тех пор, пока не появится возможность выполнить поставленную задачу. offer и poll просто возвращали значения false и null соответственно, если элемент нельзя было добавить, когда канал полон, или получить, когда канал пуст. Обе функции выдавали исключения, пытаясь работать с закрытым каналом, и вот это вызывало затруднения при их использовании.

import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() = runBlocking<Unit> {
    val channel = Channel<String>()
    launch {
        println("Sending...")
        // Doesn't suspend
        // Returns 'false' if the channel is full
        // Or throws an exception if it's closed
        channel.offer("Element")
    }
    println("Receiving...")
    // Doesn't suspend
    // Returns 'null' if the channel is empty
    println(channel.poll())
//  channel.close()
}

В приведенном примере функция poll вызывается до добавления элементов в канал и сразу же возвращает null. Обратите внимание, что она не должна использоваться таким образом. Вместо этого нужно продолжать регулярно отправлять запросы элементов, но мы для простоты примера вызываем ее напрямую. Вызвать функцию offer также не удается, поскольку это рандеву-канал с нулевым объемом буфера. В результате функция offer возвращает false, а функция poll возвращает null, просто потому что они были вызваны не в том порядке.

В этом примере можно раскомментировать строку с вызовом channel.close(), чтобы наверняка возникло исключение. Тогда poll, как и раньше, вернет false. Однако после этого offer попытается добавить элемент в уже закрытый канал и выдаст исключение. Мы получали много жалоб на то, что такое поведение чревато ошибками. Очень легко забыть обработать это исключение, а если его игнорировать или обработать иным образом, это приведет к завершению программы.

Новые функции trySend и tryReceive позволили устранить эту проблему, они выдают более подробный результат. Каждая из них возвращает экземпляр ChannelResult, который может иметь одно из трех значений: успешное выполнение, сбой или указание на то, что канал был закрыт.

import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() = runBlocking<Unit> {
    val channel = Channel<String>()
    launch {
        println("Sending...")
        // Doesn't suspend
        // Returns 'Failed' if the channel is full
        // Or 'Channel was closed' result if it's closed
        val result = channel.trySend("Element")
        println(result)

        //We can verify the result
        if(result.isClosed){
            println("Sending failed. The channel is closed.")
        }
    }
    println("Receiving...")
    println(channel.tryReceive())
//  channel.close()
}

Этот пример кода работает так же, как предыдущий, но функции tryReceive и trySend возвращают более подробный результат. Вместо false и null вы видите здесь Value(Failed). Можно снова убрать комментарий со строки, закрывающей канал, и убедиться, что trySend возвращает результат Closed, перехватывая исключение.

Благодаря inline-классам значений использование ChannelResult не создает ниже дополнительных оберток, и значение успешного выполнения возвращается без изменений и лишней траты ресурсов.

Перехватывающие функции: останавливаемые функции с инкапсуляцией ошибок

Начиная с этой версии, имена новых останавливаемых методов с инкапсуляцией ошибок получают суффикс «Catching». Например, новая функция receiveCatching обрабатывает исключение, если канал закрыт. Возьмем такой пример:

import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() = runBlocking<Unit> {
    val channel = Channel<String>()
    channel.close()
    println(channel.receiveCatching())
}

Канал был закрыт, прежде чем мы попытались получить значение. Однако выполнение программы успешно завершается с указанием, что канал был закрыт. Если вместо receiveCatching использовать обычную функцию receive, она выдаст исключение ClosedReceiveChannelException:

import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() = runBlocking<Unit> {
    val channel = Channel<String>()
    channel.close()
    println(channel.receive())
}

Пока что мы ввели только функции receiveCatching и onReceiveCatching (вместо использовавшейся ранее встроенной функции receiveOrClosed), но в дальнейшем планируем добавить новые.

Переход к использованию новых функций в коде

Во всех случаях, где в проекте используются функции offer и poll, их можно заменить автоматически с помощью новых вызовов. Поскольку offer возвращала Boolean, ее равноценной заменой станет channel.trySend("Элемент").isSuccess.

В свою очередь poll возвращает элемент, допускающий значение null, поэтому ее заменяет channel.tryReceive().getOrNull().

Если результат вызова не использован, его можно заменять напрямую с помощью нового вызова.

Теперь поведение функций при обработке исключений различается, требуемые изменения нужно внести вручную. Если код рассчитан на то, что методы «offer» и «poll» выдают исключения при закрытом канале, нужно будет сделать следующие замены.

Равноценная замена для channel.offer("Элемент") должна выдавать исключение, если канал закрыт, даже при нормальном закрытии:

channel
  .trySend("Element")
  .onClosed { throw it ?: ClosedSendChannelException("Channel was closed") }
  .isSuccess

Равноценная замена для channel.poll() выдает исключение, если канал закрыт с ошибкой, и возвращает null, если он был закрыт в нормальном режиме:

channel.tryReceive()
  .onClosed { if (it != null) throw it }
  .getOrNull()

Такие изменения соответствуют прежнему поведению функций offer и poll.

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

В версии 1.5 статус большинства функций, отвечающих за интеграцию с реактивными фреймворками, был повышен до стабильного API.

В экосистеме JVM есть ряд фремворков, которые выполняют обработку асинхронных потоков в соответствии со стандартом реактивных потоков. Два популярных фреймворка Java, которые это предлагают, — Project Reactor и RxJava.

Потоки Kotlin Flows работают иначе, и их типы несовместимы с описанными в этом стандарте, но по своей сути это тем не менее потоки. Поток Flow можно преобразовать в реактивный поток Publisher (совместимый со спецификацией и TCK) и наоборот. kotlinx.coroutines предлагает готовые конвертеры, которые можно найти в соответствующих реактивных модулях.

Например, если нужно обеспечить совместимость с типами Project Reactor, добавьте в проект следующие зависимости:

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${coroutinesVersion}")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:${coroutinesVersion}")
}

После этого можно будет использовать Flow<T>.asPublisher(), если вы хотите использовать типы Reactive Streams, или Flow<T>.asFlux(), если нужно напрямую использовать типы Project Reactor.

// acquire a Flow instance
val flow: Flow<event> = flow { … }

// Convert Flow to Publisher
val publisher = flow.asPublisher()

// Convert Flow to Reactor's Flux
val flux = flow.asFlux()

//Convert back to Flow
val anotherFlow = flux.asFlow()

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

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

Улучшенная интеграция с реактивными потоками

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

В этот раз мы присвоили статус «стабильный» длинному списку функций. Теперь можно конвертировать нужный тип из любого реактивного потока во Flow и обратно. Например, новый код может быть написан с использованием Coroutines и интегрирован со старой реактивной кодовой базой с помощью встречных конвертеров:

fun legacyFunThatHaveToReturnObservable(): Observable<int> {
  return flow<int> {
    // Use the power of flow!
  }
  // various flow operations
  .asObservable()
}

Кроме того, было внесено много улучшений в ReactorContext, который оборачивает контекст Reactor в CoroutineContext, обеспечивая полную интеграцию между Project Reactor и корутинами в Kotlin. Благодаря ей можно распространять информацию о контексте Reactor в корутинах.

Контест распространяется неявно как контекст подписчиков во всех интеграциях с реактивными потоками — Mono, Flux, Publisher.asFlow, Flow.asPublisher и Flow.asFlux. Вот простой пример распространения Context подписчика в ReactorContext:

import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.reactor.ReactorContext
import kotlinx.coroutines.reactor.asFlux

fun main() {
    val flow = flow<int> {
       println("Reactor context in Flow: " +
          currentCoroutineContext()[ReactorContext]?.context)
    }

    // No context
    // prints "Reactor context in Flow: null"
    flow.asFlux().subscribe()

    // Add subscriber's context
    // prints "Reactor context in Flow: Context1{answer=42}"
    flow.asFlux()
        .contextWrite { ctx -> ctx.put("answer", 42) }
        .subscribe()
}

В приведенном примере мы создаем экземпляр Flow, который затем преобразуется в экземпляр Reactor Flux без контекста. Вызов метода subscribe() без аргумента запрашивает у публикатора отправку всех данных. В результате программа выводит фразу «Reactor context in Flow: null».

Следующая цепочка вызовов также преобразует Flow во Flux, но затем добавляет пару ключ-значение, answer=42, к контексту Reactor для этой цепочки. Вызов subscribe() становится триггером для всей цепочки. В этом случае, поскольку контекст заполнен, программа выводит фразу «Reactor context in Flow: Context1{answer=42}»

Новые вспомогательные функции

При работе с реактивными типами, например, с Mono, в контексте корутин, можно использовать вспомогательные функции, которые позволяют получать данные, не блокируя поток. Начиная с этой версии, мы прекратили поддержку функций awaitSingleOr* для произвольных Publisher и специализировали некоторые функции await* для Mono и Maybe.

Mono генерирует не больше одного значения, так что последний элемент всегда аналогичен первому. Соответственно, семантика удаления оставшихся элементов тоже бесполезна. Поэтому поддержка Mono.awaitFirst() и Mono.awaitLast() прекращена, вместо них вводится Mono.awaitSingle().

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

Чтобы начать работу с новой версией, просто обновите содержимое файла build.gradle.kts. Сначала проверьте, что у вас установлена самая свежая версия Kotlin плагина в Gradle:

plugins {
   kotlin("jvm") version "1.5.0"
}

Затем обновите версии зависимостей, включая библиотеки, содержащие конкретные интеграции с реактивными потоками.

val coroutinesVersion = "1.5.0"

dependencies {
  implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:$coroutinesVersion")
  implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive:$coroutinesVersion")
  implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:$coroutinesVersion")
  implementation("org.jetbrains.kotlinx:kotlinx-coroutines-rx3:$coroutinesVersion")
  ...
}

Если вы столкнулись с проблемами

Ваша команда Kotlin

The Drive to Develop

Principles of Operations Management, Les Galloway – Научно-образовательный портал IQ – Национальный исследовательский университет «Высшая школа экономики»

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

    Операции — есть «процесс, метод или ряд действий, главным образом практического характера» (Collins English Dictionary, 1986). Исходя из этого определения операции есть неотъемлемый атрибут любого вида человеческой деятельности, которому свойственны организованность и продуктивность. Отсюда можно заключить, что все организационные функции есть операции и что всякая управленческая деятельность включает в себя операционный менеджмент
    Часто термины «производство» и «операции» используют как взаимозаменяемые; в промышленности, коммерческой и некоммерческой деятельности широко распространено мнение, что управление производством представляет собой отдельную, обособленную от других сферу, которая должна интересовать только тех, кто непосредственно производством и занимается. 
    Управление производством
 — исторически первая сложившаяся научная дисциплина менеджмента. Она же первой вошла и в программы преподавания. Руководители производств были, а зачастую и поныне остаются грамотными специалистами, которым можно поручить все задачи управления процессами создания продукции. Подробнее мы обсудим эту тему в главе 2, сейчас отметим лишь, что, пока производственная деятельность считалась главным источником благосостояния нации, а экономическая ситуация в целом характеризовалась недопроизводством (до 50-х годов определенно так оно и было), подобное отношение было оправданым. Однако сегодня мы переживаем период острой конкуренции, конкуренции в глобальном масштабе, и во многих странах основным источником благосостояния является уже не сфера производства, а сфера услуг.Операционный менеджмент уже не является уделом одного руководителя производства. Сектор обслуживания приобрел столь большое значение, что настала пора разобраться во всех его хитросплетениях. 
    В этой книге мы будем придерживаться взгляда, что всякая производственная деятельность представляет собой операции, а значит, операционный менеджмент имеет отношение ко всем ним.
 
    С этой принципиальной точки зрения на операции следует смотреть на показатели работы всей организации. Без четко выраженной операционной стратегии и эффективного операционного менеджмента организация может выжить лишь по чистой случайности. Таким образом, операционный менеджмент является важной дисциплиной, обязательной для руководителей всех уровней и подразделений. Однако, несмотря на принятый нами взгляд, следует признать, что наиболее очевидное и развитое его применение по-прежнему можно найти в сферепроизводства, и это неизбежно сказывается на тексте данной книги. Читателям, которых больше интересуют иные сферы созидания, мы предлагаем подумать, как можно применить описываемые далее подходы и приемы к их функциям. 
    В этой главе будут описаны природа, предназначение и структура операционной функции. В последующих разделах будет сначала рассмотрена сама операционная функция, а затем ее взаимосвязь с остальными функциями в организации. Также будут описаны основные сферы, в которых данная функция находит свое применение. В заключительной части главы мы расскажем об основных принципах организации операционной функции.

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

    Превращает готовые комплектующие части в телеприемники. Комплектующие обычно закупаются у других производителей. Производитель телевизоров, как правило, не работает с конечными потребителями, а поставляет свою продукцию дилерам для последующей продажи. Трансформация: 
    Комплектующие части — Готовый продукт

    Покупатель приобретает дорогой, сложный набор блюд, развлечение и имидж. Голод, скорее всего, играет малую роль в удовлетворении, но в целом трансформация выглядит так: 
    Покупатель ищет удовлетворения — Удовлетворенный покупатель

    Обычно посетитель приобретает лишь пищу, поэтому трансформация такая: 
    Голодный покупатель — Удовлетворенный покупатель 
    Однако большая часть производственных усилий идет на приготовление пищи: 
    Сырье — Готовые блюда 
    Таким образом, деятельность имеет смешанный характер, или фокус.

    Предполагается, что покупатель знает, чего он хочет, так что трансформация будет: 
    Покупатель с определенными потребностями (r) Удовлетворенный покупатель

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

    При переходе от коммерческих организаций к социальным, государственным и благотворительным возникают проблемы с определением покупателя. В данном случае альтернативы таковы: 
    Обвиняемый: вряд ли является покупателем, если только не будет ошибочно оправдан, но это уже недостаток качества. 
    Власти: циничный подход — поскольку большая часть избирателей не терпит преступность, власть предержащих следует рассматривать как ловцов криминальных элементов. Трансформация выглядит так: 
    Власти (r) Более популярные власти 
    Пусть каждый решит для себя, может ли он придерживаться этого взгляда. 
    Общество: общепринятое мнение таково, что преступность нежелательна, и система правосудия является одним из аспектов контроля над преступностью. Трансформация выглядит так: 
    Общество, обеспокоенное преступностью (r) Общество с более низким уровнем преступности 
    Операционный менеджмент заключается как в эффективном, так и в рациональном управлении любыми операциями. 
    ЭФФЕКТИВНОСТЬ может быть определена как достижение поставленных перед системой целей; в общем смысле эффективность — это удовлетворение потребностей покупателей. РАЦИОНАЛЬНОСТЬ — это достижение целей, или удовлетворение потребностей, с использованием минимума ресурсов.
 
    На самом примитивном уровне коммерческие организации существуют лишь за счет получения прибыли, которую можно выразить как 
    Прибыль = Доход — Затраты
 
    Благодаря своему двойному воздействию на прибыль операционный менеджмент играет жизненно важную роль в успехе организации. Главное при повышении эффективности — обеспечить такое проведение операций, чтобы удовлетворялись запросы покупателей. Организация обеспечивает покупателя услугами, которые он хочет, и так, чтобы это соответствовало его потребностям, или же производит товары, которые нужны покупателю, в соответствии с определенными спецификациями. 
    ПОВЫШЕНИЕ ЭФФЕКТИВНОСТИ увеличивает доход за счет большей конкурентоспособности организации. ПОВЫШЕНИЕ РАЦИОНАЛЬНОСТИ, несомненно, сокращает затраты, но это никогда не должно делаться в ущерб эффективности.
 
    Без правильного применения принципов операционного менеджмента организация может быть прибыльной лишь благодаря счастливой случайности. Либо она совершенно случайно сделала все так, как надо, либо конкуренты ненамного лучше нее. В любом случае маловероятно, что такое везение будет продолжаться вечно. 
    Все не так просто в некоммерческих организациях, например, местных и государственных органах власти, здравоохранении и т. д. Такими организациями движет не прибыль, поэтому их часто уличают в неэффективности; зачастую они являются монополиями, которые по определению не подвержены конкуренции, в результате чего они порождают бюрократию и индифферентны к потребностям покупателей. Мнение о них обычно формируется исходя из политических целей, а факты об эффективности их работы обычно недоступны. Тем не менее концепции эффективности и рациональности применимы и здесь. Так, повышение эффективности некоммерческих организаций предполагает, что ограниченные ресурсы не будут тратиться на недопустимую деятельность, а повышение рациональности ведет к минимизации ресурсов, требуемых для выполнения конкретных действий. 
    Чрезмерное стремление к эффективности, однако, может пагубно сказаться на качестве услуги. Например, было бы, наверное, рациональнее, если бы хозяйственные отходы собирались раз в месяц из гигантских мусорных баков, но в таком случае у домовладельцев появятся проблемы со сбором и хранением отходов, плюс угроза для здоровья — в результате оказывается, что услуга по уборке мусора более не эффективна.

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

    Выделают четыре отдельных вида деятельности, которые можно описать как операции.

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

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

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

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

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

    Рассмотрим каждую их них подробнее.

    Что может быть общего между фирмой-подрядчиком, строящей здание аэропорта или мост, и дизайнерским бюро, верстающим брошюру для своего клиента? Однако даже у самых мелких и самых масштабных операций есть определенные характеристики, за счет которых они имеют схожие структуры. К мелкомасштабным операциям, как правило, применяется термин «работа», к крупномасштабным — «проект». 
    Задачи, которые выполняет строительная компания в рамках разных проектов, могут быть в целом схожими, однако имеют существенные отличия в деталях. Не существует двух одинаковых строительных проектов. Контракт оговаривается с конкретным заказчиком, и товар или услуга изготавливаются по его, заказчика, требованиям. Каждый продукт — особенный. Из-за такого разнообразия работ или проектов информация, собранная по мере выполнения задач, может применяться в будущих контрактах лишь в обобщенном виде. Чтобы работа была закончена вовремя, а фирма, например завод тяжелого машиностроения, получила прибыль, ей приходится всецело полагаться на своих сметчиков. Точно определить объем и сроки будущих работ очень нелегко, поэтому организация должна иметь гибкую структуру и содержать некоторый излишек неиспользуемых мощностей. Гибкости можно достичь за счет работников, обладающих сразу несколькими навыками, либо путем привлечения субподрядчиков. Оборудование обычно принадлежит самой компании, но часть его может простаивать, поскольку может понадобиться для обслуживания очередного заказа. Та часть оборудования, что используется нечасто, может быть взята в аренду лишь в случае необходимости — если, конечно, его можно будет быстро арендовать. Система планирования и контроля во многом зависит от субъективной оценки целей, в то время как контроль прогресса ведется по завершении отдельных стадий работы или проекта.

Если спрос на отдельный ресурс, функцию или технологию достаточно велик, при его покрытии можно добиться снижения себестоимости единицы продукции. Этот принцип применяется при серийной организации работы, когда производится ограниченная номенклатура товаров или услуг. При этом партия (серия) из нескольких штук (или нескольких тысяч штук) изделий обрабатывается сразу целиком, как один объект. Каждое изделие проходит в определенной последовательности через те же этапы производства, что и все остальные; операции осуществляются с использованием одного и того же оборудования. Поскольку продукты стандартизованы, из прошлого опыта будет известно точное количество необходимых станков, рабочей силы, материалов и времени, что позволяет качественно проводить планирование и контроль. Поэтому появляется возможность заблаговременного (на этапе планирования) формирования схем производственных процессов для цехов и отдельных участков. 
    В качестве простого примера возьмем производство таблеток — аспирина, от боли в животе или просто мятных конфет. Процесс их изготовления может состоять из трех этапов: смешивание, когда производится перемешивание всех ингредиентов, прессование, когда образуются сами таблетки, и, так сказать, обработка, когда таблетки инспектируются и упаковываются. Все смешивающие машины группируются в одном месте, управляются определенной группой рабочих и контролируются одним мастером. То же относится к прессованию и обработке. 
    У такой организации есть несколько преимуществ. Разделение на отдельные технологические процессы с общими навыками, приемами и проблемами представляет собой удобную базу для планирования и контроля. Работа изолируется по соответствующим участкам, а ее прогресс отслеживается по прохождению заготовок с одного процесса на другой. В рамках процесса также может производиться контроль качества, когда со следующей стадии партию отправляют назад, если она не отвечает определенным требованиям. Одного и того же человека можно назначить ответственным как за управление, так и за техническое содержание участка. Как правило, работа в рамках участка носит гибкий характер (то есть оператор смесителя может управлять любой машиной на своем участке), что позволяет более эффективно использовать рабочую силу. В целом, однако, загрузка производственных мощностей завода может понизиться, потому что конкретные продукты требуют конкретного оборудования, но могут производиться в количествах, недостаточных для их полной загрузки.

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

    В этой главе представлена концепция операционной функции и кратко рассмотрены ее взаимосвязи с остальными функциональными областями компании. Также представлен тетраэдр операций как средство для описания главной функции организации, дан обзор альтернативных способов организации операций. Успех всего предприятия всецело зависит от соответствия плана, организации и контроля над операциями главной функции организации, а далее от обеспечения ее эффективной работы. Теме соответствия будут посвящены главы 2, 3 и 4, оставшаяся часть книги охватывает вопросы эффективной организации. 
    Эффективность и рациональность операционного менеджмента целиком и полностью зависят от правильности выбора операционной стратегии. Если операционная функция не имеет четких, согласованных и достижимых целей, можно не сомневаться, что вскоре она перестает оправдывать ожидания. 
    К сожалению, во многих организациях явно выраженной стратегии нет вовсе, а там, где общая стратегия деятельности все же имеется, операционной функции зачастую уделяют слишком мало внимания. 
    Существуют производственные компании, которые ведут себя так, будто их операционная стратегия заключается в изготовлении всего, что ни пожелает покупатель, в любом количестве, по наименьшей возможной цене и с максимально высоким качеством. Это, разумеется, нереальная цель, но в отделах продаж почему-то считают, что на производстве могут ее достичь. Когда этого не происходит, винят производство. Операционные менеджеры слишком часто считают себя совершенно реактивными, всегда готовыми удовлетворить потребности рынка (как их представляют себе сбытовики) и настолько занятыми борьбой с проблемами, порождаемыми этой невыполнимой миссией, что времени на создание вразумительной стратегии для самих себя у них уже не остается. 
    В главе 1 мы показали, что операционная функция является ключом к успешной конкуренции. 
    Без эффективной и рационально организованной операционной функции ни одна организация не может удержать за собой лидерство на рынке, поскольку она проиграет в скорости доставки, цене или качестве, а скорее всего — по всем трем показателям.
 
    В этой главе будут рассмотрены все основные элементы согласованной операционной стратегии. Будут изучены составляющие корпоративной и рыночной стратегий, оказывающие влияние на операции, и возможности построения операционной стратегии на их основе. В заключительной части главы будет рассказано о применении метода профилирования для выявления несоответствий в текущей деятельности и требованиях рынка, а также о преимуществах упреждающих операционных действий по отношению к корпоративной стратегии.

    Операции — есть «процесс, метод или ряд действий, главным образом практического характера» (Collins English Dictionary, 1986). Исходя из этого определения операции есть неотъемлемый атрибут любого вида человеческой деятельности, которому свойственны организованность и продуктивность. Отсюда можно заключить, что все организационные функции есть операции и что всякая управленческая деятельность включает в себя операционный менеджмент. 

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

    Управление производством — исторически первая сложившаяся научная дисциплина менеджмента. Она же первой вошла и в программы преподавания. Руководители производств были, а зачастую и поныне остаются грамотными специалистами, которым можно поручить все задачи управления процессами создания продукции. Подробнее мы обсудим эту тему в главе 2, сейчас отметим лишь, что, пока производственная деятельность считалась главным источником благосостояния нации, а экономическая ситуация в целом характеризовалась недопроизводством (до 50-х годов определенно так оно и было), подобное отношение было оправданым. Однако сегодня мы переживаем период острой конкуренции, конкуренции в глобальном масштабе, и во многих странах основным источником благосостояния является уже не сфера производства, а сфера услуг. Операционный менеджмент уже не является уделом одного руководителя производства. Сектор обслуживания приобрел столь большое значение, что настала пора разобраться во всех его хитросплетениях. 

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

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

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

 

Что такое операционный менеджмент?

 

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

    Операционный менеджмент — это деятельность по управлению процессом приобретения материалов, их превращения в готовый продукт и поставкой этого продукта покупателю. 

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

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

    Более точное определение, таким образом, может звучать так: 

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

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

 

Производитель телевизоров

 

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

    Комплектующие части — Готовый продукт

 

Эксклюзивный ресторан

 

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

    Покупатель ищет удовлетворения — Удовлетворенный покупатель

 

Закусочная быстрого обслуживания

 

    Обычно посетитель приобретает лишь пищу, поэтому трансформация такая: 

    Голодный покупатель — Удовлетворенный покупатель 

    Однако большая часть производственных усилий идет на приготовление пищи: 

    Сырье — Готовые блюда 

    Таким образом, деятельность имеет смешанный характер, или фокус.

 

Супермаркет самообслуживания

 

    Предполагается, что покупатель знает, чего он хочет, так что трансформация будет: 

    Покупатель с определенными потребностями (r) Удовлетворенный покупатель

 

Страховая компания

 

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

    Модель инвестиций в трансформации может выглядеть так: 

    Покупатель с некоторой суммой денег — Покупатель с большей суммой денег 

    Однако в случае защиты истинно удовлетворенный покупатель — тот, с которым ничего не произошло, а поскольку это компании неподконтрольно, ее альтернативой будет: 

    Покупатель, страдающий от потери — Покупатель с финансовой компенсацией за потерю 

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

    Покупатель, которому необходима финансовая консультация — Правильно проконсультированный покупатель — Покупатель, которому необходима компенсация — Покупатель, получивший компенсацию

 

Система правосудия

 

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

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

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

    Власти (r) Более популярные власти 

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

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

    Общество, обеспокоенное преступностью (r) Общество с более низким уровнем преступности 

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

    ЭФФЕКТИВНОСТЬ может быть определена как достижение поставленных перед системой целей; в общем смысле эффективность — это удовлетворение потребностей покупателей. РАЦИОНАЛЬНОСТЬ — это достижение целей, или удовлетворение потребностей, с использованием минимума ресурсов. 

    На самом примитивном уровне коммерческие организации существуют лишь за счет получения прибыли, которую можно выразить как 

    Прибыль = Доход — Затраты 

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

    ПОВЫШЕНИЕ ЭФФЕКТИВНОСТИ увеличивает доход за счет большей конкурентоспособности организации. ПОВЫШЕНИЕ РАЦИОНАЛЬНОСТИ, несомненно, сокращает затраты, но это никогда не должно делаться в ущерб эффективности. 

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

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

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

 

Операционная функция в организации

 

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

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

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

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

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

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

 

Операции как виды деятельности

 

    Выделают четыре отдельных вида деятельности, которые можно описать как операции.

 

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

Поставки. Деятельность, связанная главным образом с переменой права собственности на физический товар. Наиболее ярким примером являются дистрибьюторские сети.

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

Сервис. Деятельность, связанная с изменением состояния покупателя. Речь может идти о физическом состоянии, как в случае со стоматологией и парикмахерскими услугами, интеллектуальном, как в случае с образованием и консалтингом, или, чаще, о сложном сочетании этих и других состояний.

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

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

 

Материальные потоки

 

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

 

Производство и поставки

 

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

 

Модель 1. Самая распространенная система. Ее преимущество для производства в том, что достигается максимальная эффективность производственного процесса, поскольку поставки сырья гарантированы и нет необходимости быстро реагировать на изменения покупательского спроса — для этого создаются запасы. Запасы в данном случае «изолируют» производство от превратностей как поставок, так и спроса. Такая же модель применяется в сфере розничного распределения, где запас товаров содержится на складе, выносится по мере необходимости на прилавки и хранится на них, опять же в виде запаса, пока не будет раскуплен. Использование запаса для изоляции разных этапов друг от друга значительно упрощает управленческую работу, но одновременно с этим вносит свои ограничения и неудобства. Самой очевидной проблемой является стоимость хранения запасов, о чем будет рассказано в главе 8. Данная модель может применяться лишь в условиях, когда существует спрос на определенный ассортимент продуктов. В случае изготовления на заказ запас готовой продукции не может быть создан ни при каких условиях.

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

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

Модель 4. Существуют фирмы посылочной торговли, которые принимают заказы на доставку товаров по почте. Они дают рекламу продукта, принимают заказы, передают их производителю, который затем изготавливает и доставляет продукт. Фирма просто занимается администрированием заказов и, если деньги за продукт платятся вперед, получает свой процент в период между получением заказа и оплатой счета производителя. При такой организации работы применима модель 4. Таким образом, данная модель применима в большинстве случаев позаказного производства, когда не требуется запас сырья и материалов. К примеру, в гражданском строительстве материалы обычно закупаются под конкретные проекты, вместо того чтобы создавать огромные запасы, а готовый продукт попасть в запас не может в принципе. Стремление сократить затраты на хранение и повысить скорость реакции системы привела к появлению стратегии производства под названием «точно-вовремя». Конечная цель этого подхода — нулевые запасы на всех стадиях, таким образом, ему полностью соответствует модель 4. Этой теме будет посвящена глава 10.

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

 

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

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

 

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

Модель 2. Эта модель характерна для дешевых услуг. Ресурсы используются полностью, отсюда более высокая эффективность, но при этом покупателям приходится ждать. Контраст между моделями 1 и 2 как нельзя лучше иллюстрируется на примере частной и государственной медицины. Хотя в частных клиниках не всегда попадаешь к врачу без очереди, ждать обычно приходится гораздо меньше, а назначенное время — это всегда время визита в кабинет, нежели время для присоединения к очереди таких же ждущих. Фирмы, занимающиеся курьерской доставкой, обычно предлагают два вида услуг: гарантированную доставку на следующий день и доставку за гораздо менее определенный срок, в качестве которого обычно называется среднее, нежели максимальное, время нахождения корреспонденции в пути. Для каждой из этих услуг используются одни и те же мощности, поэтому отпадает необходимость в содержании избытка для покрытия неожиданных всплесков спроса на «доставку за 24 часа». Если спрос на такую услугу возрастает, необходимые мощности можно позаимствовать, удлиняя время доставки «обычной» корреспонденции. Если же спрос на нее падает, качество стандартной услуги вновь улучшается.

Модель 3. Ее можно рассматривать как образец неэффективного управления — простаивающие ресурсы и ожидающие в очереди покупатели, тем не менее она моделирует работу большинства сервисных операций в краткосрочном периоде. Для большинства услуг характерны быстрые и значительные колебания спроса. Например, питейные заведения, рестораны и отделения травматологии при больницах пользуются наибольшим спросом по выходным, на общественном транспорте значительные колебания спроса характерны в рабочие дни с 8.30 до 9.30 утра и т. д. Поскольку добавить или убавить мощности с такой же быстротой невозможно, у руководства не остается иного выбора, кроме как создавать подобие очереди в периоды пиковой нагрузки и мириться с некоторым переизбытком ресурсов в остальное время. Снижение платы за проезд и скидки для пенсионеров в часы наименьшей нагрузки — примеры попыток как-то использовать простаивающий транспорт.

Организация труда

 

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

 

производство по работам/проектам;

серийное производство;

поточное/массовое производство.

    Рассмотрим каждую их них подробнее.

 

Организация производства по работам/проектам

 

    Что может быть общего между фирмой-подрядчиком, строящей здание аэропорта или мост, и дизайнерским бюро, верстающим брошюру для своего клиента? Однако даже у самых мелких и самых масштабных операций есть определенные характеристики, за счет которых они имеют схожие структуры. К мелкомасштабным операциям, как правило, применяется термин «работа», к крупномасштабным — «проект». 

    Задачи, которые выполняет строительная компания в рамках разных проектов, могут быть в целом схожими, однако имеют существенные отличия в деталях. Не существует двух одинаковых строительных проектов. Контракт оговаривается с конкретным заказчиком, и товар или услуга изготавливаются по его, заказчика, требованиям. Каждый продукт — особенный. Из-за такого разнообразия работ или проектов информация, собранная по мере выполнения задач, может применяться в будущих контрактах лишь в обобщенном виде. Чтобы работа была закончена вовремя, а фирма, например завод тяжелого машиностроения, получила прибыль, ей приходится всецело полагаться на своих сметчиков. Точно определить объем и сроки будущих работ очень нелегко, поэтому организация должна иметь гибкую структуру и содержать некоторый излишек неиспользуемых мощностей. Гибкости можно достичь за счет работников, обладающих сразу несколькими навыками, либо путем привлечения субподрядчиков. Оборудование обычно принадлежит самой компании, но часть его может простаивать, поскольку может понадобиться для обслуживания очередного заказа. Та часть оборудования, что используется нечасто, может быть взята в аренду лишь в случае необходимости — если, конечно, его можно будет быстро арендовать. Система планирования и контроля во многом зависит от субъективной оценки целей, в то время как контроль прогресса ведется по завершении отдельных стадий работы или проекта.

 

Организация серийного производства

 

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

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

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

 

Организация поточного/массового производства

 

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

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

 

Резюме

 

    В этой главе представлена концепция операционной функции и кратко рассмотрены ее взаимосвязи с остальными функциональными областями компании. Также представлен тетраэдр операций как средство для описания главной функции организации, дан обзор альтернативных способов организации операций. Успех всего предприятия всецело зависит от соответствия плана, организации и контроля над операциями главной функции организации, а далее от обеспечения ее эффективной работы. Теме соответствия будут посвящены главы 2, 3 и 4, оставшаяся часть книги охватывает вопросы эффективной организации. 

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

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

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

    В главе 1 мы показали, что операционная функция является ключом к успешной конкуренции. 

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

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

 

закрыть

 

Предисловие к первому изданию 

Предисловие ко второму изданию 

 

Глава 1. Операционный менеджмент и операционная функция

 

Что такое операционный менеджмент? 

Операционная функция в организации 

Операции как виды деятельности 

Материальные потоки 

Организация труда

Глава 2. Операционная стратегия

 

Корпоративные факторы 

Сервис и его смысл 

Операционная стратегия 

Согласование операционной и рыночной стратегий

Глава 3. Проектирование продукта

 

Проектирование продукта 

Разнообразие и стандартизация 

Качество и надежность 

Стоимостной анализ и стоимостной инжиниринг

Глава 4. Разработка услуги

 

Характеристики услуги 

Индустриализация в разработке услуг 

Качество сервиса

Глава 5. Планирование производственных мощностей

 

Предварительные решения 

Выбор места 

Один объект или несколько? 

Составление плана размещения оборудования

Глава 6. Организация производственного процесса

 

Распределение задач 

Автоматизация 

Организация работы 

Анализ рабочего времени

Глава 7. Планирование и контроль 1 — планирование загрузки производственных мощностей

 

Спрос и его прогнозирование 

Колебания спроса 

Система планирования 

Линейное программирование

Глава 8. Управление запасами

 

Типы запасов 

Затраты на ведение запасов 

Определение оптимального соотношения затрат 

Системы управления запасами 

Выбор системы управления запасами 

Контроль

Глава 9. Планирование и контроль 2 — календарное планирование производства

 

Последовательное календарное планирование 

Практические методы календарного планирования 

Планирование материального обеспечения 

Планирование производственных ресурсов 

Работа системы 

Оптимизация технологии производства

Глава 10. Планирование и контроль 3 — система «точно-вовремя»

 

Точно-вовремя 

Внедрение системы «точно-вовремя» 

Применение и ограничения Т-В 

Кайзен

Глава 11. Планирование и контроль проектов

 

Сетевое планирование 

Анализ длительности

Глава 12. Управление качеством

 

Определение качества 

Цена качества 

Статистический контроль качества 

Предупреждающее управление качеством 

Управление тотальным качеством 

Стандарты качества 

Качество сервиса

Глава 13. Техническое обслуживание

 

Реакционный и профилактический подходы 

Предупреждающий подход 

Политика технического обслуживания

Приложение 1. Количественные методы в операционном менеджменте

Приложение 2. Введение в контрольные карты

Приложение 3. История развития ключевых концепций операционного менеджмента

Литература

Именной указатель

Предметный указатель

Указатель фирм и торговых марок

Реактивная функция

— RDocumentation

Описание

Обертывает обычное выражение для создания реактивного выражения. Концептуально реактивное выражение — это выражение, результат которого со временем будет меняться.

Использование

 реактивное (
  Икс,
  env = parent.frame (),
  quoted = ЛОЖЬ,
  ...,
  метка = NULL,
  домен = getDefaultReactiveDomain (),
  ..stacktraceon = ИСТИНА
) 

is.reactive (x)

Аргументы

x

Для is.reactive () , объект для тестирования.Для reactive () — выражение. При передаче quo () sure с reactive () , не забудьте использовать rlang :: inject () , чтобы различать, что вы передаете содержание вашего запроса, а не его выражение.

env

Родительская среда для реактивного выражения. По умолчанию, это вызывающая среда, такая же, как при определении обычного нереактивное выражение. Если x — это предложение, а в кавычках — это ИСТИНА , тогда env игнорируется.

quoted

Если это ИСТИНА , то quote () ed значение x будет использоваться при оценке x . Если x — это вопрос, и вы хотите использовать его выражение в качестве значения x , тогда вы должны установить цитируется с по ИСТИНА .

label

Метка для реактивного выражения, полезная для отладки.

..stacktraceon

Только для расширенного использования. Для манипулирования стеком; видеть stacktrace () .

Значение

функция, заключенная в класс S3 «реактивный»

Подробности

Реактивные выражения — это выражения, которые могут считывать реактивные значения и вызывать другие реактивные выражения. Всякий раз, когда реактивное значение изменяется, любое реактивное выражения, зависящие от него, помечаются как «недействительные» и будут автоматически повторно выполнить при необходимости. Если реактивное выражение помечено как аннулированы, любые другие реактивные выражения, которые недавно вызвали его, также помечено как недействительное.Таким образом, недействительность проходит через выражения, которые зависят друг от друга.

См. Руководство по Shiny для больше информации о реактивных выражениях.

Примеры

 # NOT RUN {
библиотека (rlang)
значения <- reactiveValues ​​(A = 1)

reactiveB <- реактивный ({
  значения $ A + 1
})
# Просмотр значений из консоли R с помощью isolate ()
изолировать (reactiveB ())
# 2

# Чтобы сохранить выражения для последующего преобразования в реактивные, используйте quote ()
myquo <- rlang :: quo (значения $ A + 2)
# Неожиданное значение! Отправка запроса напрямую не сработает.reactiveC <- реактивный (myquo)
# Мы надеемся на `3`, но вместо этого получаем предложение, которое было поставлено.
изолировать (reactiveC ())

# Вместо этого вопрос должен быть `rlang :: inject ()` ed
reactiveD <- rlang :: inject (реактивный (!! myquo))
изолировать (reactiveD ())
# 3

# (Legacy) Можно использовать выражения в кавычках
выражение <- цитата ({значения $ A + 3})
reactiveE <- реактивный (выражение, кавычки = ИСТИНА)
изолировать (reactiveE ())
# 4

#}
 

Реактивные и функциональные полимеры | Журнал

Цели и область применения

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

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

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

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

Посмотреть все цели и масштабы

Гош, Дебасиш: 9781617292248: Amazon.com: Книги

Резюме

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

Приобретая печатную книгу, вы получаете бесплатную электронную книгу в форматах PDF, Kindle и ePub от Manning Publications.

О технологии

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

О книге

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

Об авторе

Архитектор программного обеспечения Дебасиш Гош был одним из первых приверженцев реактивного проектирования с использованием Scala и Akka.Он является автором DSL in Action , опубликованных Manning в 2010 году.

Оглавление

  1. Моделирование функциональной области: введение
  2. Scala для моделей функциональной области
  3. Разработка моделей функциональной области
  4. Функциональные шаблоны для модели предметной области
  5. Модуляризация моделей предметной области
  6. Реагирующая
  7. Моделирование с реактивными потоками
  8. Реактивное постоянство и поиск событий
  9. Тестирование модели предметной области
  10. Резюме - основные мысли и принципы

Произошла ошибка при настройке вашего пользовательского файла cookie

Этот сайт использует файлы cookie для повышения производительности.Если ваш браузер не принимает файлы cookie, вы не можете просматривать этот сайт.


Настройка вашего браузера для приема файлов cookie

Существует множество причин, по которым cookie не может быть установлен правильно. Ниже приведены наиболее частые причины:

  • В вашем браузере отключены файлы cookie. Вам необходимо сбросить настройки своего браузера, чтобы он принимал файлы cookie, или чтобы спросить вас, хотите ли вы принимать файлы cookie.
  • Ваш браузер спрашивает вас, хотите ли вы принимать файлы cookie, и вы отказались.Чтобы принять файлы cookie с этого сайта, нажмите кнопку «Назад» и примите файлы cookie.
  • Ваш браузер не поддерживает файлы cookie. Если вы подозреваете это, попробуйте другой браузер.
  • Дата на вашем компьютере в прошлом. Если часы вашего компьютера показывают дату до 1 января 1970 г., браузер автоматически забудет файл cookie. Чтобы исправить это, установите правильное время и дату на своем компьютере.
  • Вы установили приложение, которое отслеживает или блокирует установку файлов cookie.Вы должны отключить приложение при входе в систему или проконсультироваться с системным администратором.

Почему этому сайту требуются файлы cookie?

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


Что сохраняется в файле cookie?

Этот сайт не хранит ничего, кроме автоматически сгенерированного идентификатора сеанса в cookie; никакая другая информация не фиксируется.

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

Функциональное реактивное программирование на Angular с RxJS

Наряду с React и Vue, Angular считается одной из лучших фреймворков JS UI.Однако он отличается парой факторов. В отличие от двух других топ-2, это полноценный фреймворк, включающий все, что вам нужно от фреймворка. Он также имеет уникальную архитектуру и идеологию. Это можно увидеть в том, что его основным языком является TypeScript вместо JavaScript, интенсивное использование декораторов и заметное влияние парадигмы функционального реактивного программирования и принятие многих из ее шаблонов.

Функциональное реактивное программирование

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

В Angular FRP используется в основном через Observables . Они, в свою очередь, создают интерфейс для обработки асинхронных операций, таких как запросы AJAX или события пользовательского ввода. Все это и многое другое реализовано с помощью библиотеки RxJS .

Что такое RxJS?

Библиотека RxJS (Reactive Extensions for JavaScript) предоставляет реализацию Observables для JavaScript наряду с другими «вспомогательными» типами и операторами для работы с ними.Все эти функции составляют надежный инструментарий для функциональной и реактивной работы с асинхронными операциями.

В целом, это библиотека , к которой можно обратиться всякий раз, когда вы имеете дело с FRP на JS или любом другом языке, поддерживаемом проектом ReactiveX. Вот почему Angular и многие другие проекты выбирают его в качестве наблюдаемой реализации и формируют основу для чистой кодовой базы FRP.

Observables

Чтобы правильно понять RxJS и FRP в целом, мы должны начать с концепции наблюдаемых .

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

Наблюдаемые объекты играют роль функциональных оберток вокруг таких потоков. Они предоставляют вам способ подписаться на поток и отказаться от подписки (для прослушивания входящих значений) и API-интерфейсы для преобразования входящих данных в соответствии с вашими потребностями.

Создание наблюдаемых

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

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

 Копировать 

1import {Observable} из "rxjs";

2

3const observable $ = new Observable ((подписчик) => {

4 let count = 0;

5 const interval = setInterval (() => {

6 subscriber.следующий (счетчик);

7 счет ++;

8}, 1000);

9

10 return () => {

11 clearInterval (интервал);

12};

13});

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

Все, что присваивается переменной, оканчивающейся на $ - не требование, а общее соглашение об именах для наблюдаемых.

Функции создания

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

 Скопируйте 

1import {interval} из "rxjs";

2

3конст. Наблюдаемая $ = интервал (1000);

Коротко и просто. RxJS полон таких функций.Позвольте мне показать вам несколько примеров:

 Скопируйте 

1import {from, fromEvent, of} из "rxjs";

2импорт {fromFetch} из "rxjs / fetch";

3

4from (выборка ("/ example.json"));

5из ([1, 2, 3, 4]);

6fromEvent (document.getElementById ("btn"), "щелчок");

7из (1, 2, 3, 4);

8fromFetch ("/ example.json");

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

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

Итак, из ([1,2,3]) приведет к наблюдаемой последовательности из 1 элемента ( [1,2,3] ), а из ([1,2,3]) приведет к последовательности 3 ( 1 , 2 , 3 ). Имейте в виду, что то же самое относится и к строкам типа Array (e.грамм. "тест" по сравнению с "t" , "e" , "s" , "t" ).

fromEvent () приближается к пользовательскому интерфейсу, поскольку он создает наблюдаемую из событий пользовательского интерфейса . Дайте цели название события, и готово!

И последнее, но не менее важное: fromFetch () предоставляет ярлык для создания наблюдаемого напрямую из fetch () . Это проще и чище, чем использовать из (fetch ()) .

RxJS содержит такие функции, как из () , из () или изFetch () .Он предоставляет вам несколько способов сделать одно и то же, каждый из которых подходит для разных сценариев. Это как Lodash для наблюдаемых - очень полезно, с множеством вариантов выбора.

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

Подписки

Давайте вернемся к нашему простому примеру interval () и посмотрим, как мы можем подписаться на для получения обновлений.

 Копировать 

1импорт {интервал} из "rxjs";

2

3конст. Наблюдаемая $ = интервал (1000);

4const subscription = наблюдаемая $ .subscribe ((значение) => {

5 console.log (значение);

6});

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

 Копия 

1

2

3

4observable $.подписаться (

5 (значение) => {

6 console.log (значение);

7},

8 (ошибка) => {

9 console.error (ошибка);

10},

11 () => {

12 console.log ("полный");

13}

14);

15

16observable $ .subscribe ({

17 next (value) {

18 console.log (value);

19},

20 error (error) {

21 console.error (ошибка);

22},

23 завершено () {

24 console.log ("завершено");

25},

26});

Ни один из упомянутых обратных вызовов не требуется, хотя вам наверняка понадобится хотя бы один.

Кроме того, имена обратных вызовов ( следующий , ошибка и полный ) эквивалентны методам, которые вы используете для управления потоком уведомлений с наблюдаемой стороны. В нашем настраиваемом интервале наблюдаемых мы использовали только next () , но, наряду с другими методами, также доступны error () и complete () . Отписаться Возвращенный объект подписки (результат вызова subscribe () ) удобен для управления подпиской - что наиболее важно - отписки от нее. Имея доступ к объекту подписки, мы можем отписаться от с помощью простого вызова unsubscribe () .

 Копировать 

1subscription.unsubscribe ();

Отказ от подписки важен, поскольку он управляет правильным выполнением наблюдаемых и вызовов функций удаления для предотвращения утечек памяти .Поэтому, когда вы закончите использовать подписку, не забудьте позвонить по номеру unsubscribe () . Множественные подписки Еще одна вещь, связанная с подписками, которую стоит обсудить: что происходит, когда вы подписываетесь на одно и то же наблюдаемое более одного раза?

 Копия 

1

2

3конст. Наблюдаемая $ = интервал (1000);

4

5observable $ .subscribe ((значение) => {

6 console.log («Подписка A», значение);

7});

8setTimeout (() => {

9 наблюдаемых $.subscribe ((значение) => {

10 console.log («Подписка B», значение);

11});

12}, 2000);

13

14

15

16

17

18

19

20

21

Обратите внимание, что у нас разные значения для обеих подписок, даже если мы подписались на одну и ту же наблюдаемый. Оба они имеют отдельные интервалы, которые можно увидеть в выводе, особенно с добавленным вызовом setTimeout () .

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

Frontend Monitoring

Отладка веб-приложения в производственной среде может быть сложной и трудоемкой. OpenReplay - это стек воспроизведения сеанса с открытым исходным кодом для разработчиков. Это помогает вам воспроизвести все, что делают ваши пользователи, и показывает, как ваше приложение ведет себя при каждой проблеме. Это похоже на то, как если бы инспектор браузера был открыт, а пользователь смотрит через плечо. OpenReplay позволяет воспроизводить проблемы, агрегировать ошибки JS и отслеживать производительность вашего приложения.OpenReplay предлагает плагины для захвата состояния вашего хранилища Redux или VueX , а также для проверки запросов Fetch и запросов GraphQL . Удачной отладки для современных команд, работающих с интерфейсами - начните бесплатно отслеживать свое веб-приложение.

Горячий или холодный

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

Являясь источником данных наблюдаемого, производитель может быть создан либо «внутри», , либо «вне» наблюдаемого.

Вы можете ясно увидеть это в нашем примере создания наблюдаемого интервала с нуля.

 Копировать 

1import {Observable} из "rxjs";

2

3const observable $ = new Observable ((подписчик) => {

4 let count = 0;

5 const interval = setInterval (() => {

6 subscriber.next (count);

)

7 count ++;

8}, 1000);

9

10 return () => {

11 clearInterval (interval);

12};

13});

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

Это дает несколько интересных свойств:

  • Новый производитель создается для каждой подписки;
  • Для новой подписки будет возвращена та же последовательность значений;
  • Значения начинают отправляться только после первой подписки (поскольку до этого производителя не существовало).

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

Однако, когда мы рассматриваем наблюдаемые объекты, обертывающие события пользовательского ввода или запросы AJAX, мы соответственно будем вынуждены использовать горячие наблюдаемые объекты или будем очень осторожны, чтобы не вызывать ненужные запросы с холодными наблюдаемыми объектами. Также существует вероятность утечки памяти, когда мы забываем о неиспользуемых, работающих наблюдаемых (особенно холодных).

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

 Копировать 

1import {Observable} из "rxjs";

2

3let count = 0;

4

5const intervalCallbacks = [];

6setInterval (() => {

7 intervalCallbacks.forEach ((callback) => callback (count));

8 count ++;

9}, 1000);

10const observable $ = new Observable ((подписчик) => {

11 const callback = (count) => {

12 subscriber.next (count);

13};

14 intervalCallbacks.push (обратный вызов);

15

16 return () => {

17 intervalCallbacks.splice (intervalCallbacks.indexOf (callback), 1);

18};

19});

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

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

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

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

Все холодно, если иное не имеет реального смысла.

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

Еще одна важная вещь, на которую следует обратить внимание, - это fromFetch () и другие наблюдаемые, связанные с HTTP-запросами, например, из Angular HttpClient . Все они , холодные , поэтому, хотя вы можете легко управлять своими запросами с их помощью, вам все равно придется следить за собой, поскольку каждая подписка приведет к другому запросу .

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

AsyncPipe

Мы уже рассмотрели, как вы можете подписаться на наблюдателя и как вы можете управлять подпиской с помощью метода unsubscribe () для объекта подписки или, например, complete () внутри наблюдаемого объекта “ план ».

Однако в Angular есть еще один способ управления подписками, о котором вы должны знать, - это AsyncPipe . Это позволяет вам подписаться на наблюдаемое прямо из шаблона Angular.Более того, он автоматически вызовет unsubscribe () , когда ваш компонент будет уничтожен, что значительно упростит управление подпиской и предотвращение утечки памяти. Он также будет автоматически использовать последнее значение из потока, обновлять представление по мере необходимости и даже повторно подписываться на новый наблюдаемый объект, если это необходимо.

Что касается использования, AsyncPipe имеет простую форму | async , помещается сразу после наблюдаемого (или обещания) выбора. В следующем примере мы используем его для доступа к данным наблюдаемого объекта продуктов и долларов США, просматриваем их и выводим результаты.

 Копия 

1

2

3 @ Component ({

4 шаблон: `

    5

  • {{product.name}} < / li>

    6

`,

7

8})

9export class AsyncObservablePipeComponent {

10 продуктов $: Observable = this.productsService.getProducts ();

11

12}

Операторы

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

Теперь пора поговорить об операторах - API манипуляций , которые делают «Функциональный» в FRP действительно ярким.

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

Интересный факт: мы уже познакомились с некоторыми операторами. Так называемые «функции создания» на самом деле являются одним из двух типов операторов - операторы создания .

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

Метод трубы

Оператор можно использовать двумя способами. Первый - просто вызвать его и передать ему наблюдателя.Для оператора с именем operator () он будет выглядеть так:

 Копировать 

1const newObservable $ = operator () (observable $);

Обратите внимание на первые пары скругленных скобок. Он используется для создания / настройки оператора. Если нужны какие-то аргументы, они пойдут сюда. Если нет - вызов остается для согласованности API.

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

Вот где приходит на помощь метод Observable ’s pipe () . Он позволяет вам соединять несколько операторов по конвейеру с четким, читаемым синтаксисом.

 Копировать 

1const newObservable $ = наблюдаемый $ .pipe (

2 operator (),

3 operatorA (),

4 operatorB (),

5 operatorC (),

6 operatorD ()

7 );

Синтаксис pipe () на самом деле настолько предпочтителен, что в рекомендуется использовать его даже для одиночных операторов.

Общие операторы

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

Подобно массивам, наблюдаемые объекты и базовые потоки представляют последовательности данных - просто асинхронно. Вот почему многие операторы делятся своими примерами использования и именами с методами массива. Итак, у нас есть filter () , map () , every () , find () , reduce () и многие другие.

Что касается некоторых примеров использования:

 Скопируйте 

1import {of} из "rxjs";

2import {каждый, фильтр, найти, сопоставить, уменьшить} из "rxjs / operator";

3

4конст. Наблюдаемая $ = из (1, 2, 3, 4, 5);

5

6

7const filterObservable $ = наблюдаемый $ .pipe (

8 filter ((value) => value% 2 === 0)

9);

10

11

12

13

14observable $ .pipe (map ((value) => value * value));

15

16 наблюдаемый $.труба (каждый ((значение) => значение> 1));

17

18observable $ .pipe (find ((value) => value === 4));

19

20observable $ .pipe (уменьшить ((аккумулятор, значение) => аккумулятор + значение));

21

22

23filteredObservable $ .subscribe ((значение) => {

24 console.log (значение);

25});

Обратите внимание, как операторы импортируются из отдельного модуля - rxjs / operator - вероятно, для организации, поскольку их так много!

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

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

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

 Копировать 

1import {fromFetch} из «rxjs / fetch»;

2import {concatAll, filter, map} из "rxjs / operator";

3

4const наблюдаемый $ = fromFetch ("/ example.json ", {

5 селектор (ответ) {

6 return response.json ();

7},

8})

9 .pipe (

10 concatAll (),

11 фильтр ( (значение) => {

12 value.experience> = 10;

13}),

14 map ((value) => value.name)

15)

16 .subscribe ((value) = > {

17 console.log (значение);

18});

В fromFetch () , помимо URL-адреса запроса, мы передаем объект конфигурации с помощью функции обратного вызова selector () для «разворачивания» извлеченные данные.

Затем, предполагая, что данные JSON представляют собой массив объектов, описывающих пользователей, мы обрабатываем его с помощью нескольких операторов. Сначала concatAll () «разбивает» входной массив на отдельные элементы последовательности, которые затем обрабатываются с помощью filter () и map () . Все чисто и функционально.

Операторы в UI

Помимо обработки данных, наблюдаемые и операторы также могут быть полезны в UI - особенно при работе с событиями пользовательского ввода .Рассмотрим следующий пример, где мы используем функцию создания fromEvent () и оператор filter () для определения количества нажатий на кнопку Angular:

 Копировать 

1import {

2 AfterViewInit,

3 Component,

4 ElementRef,

5 EventEmitter,

6 Вход,

7 Выход,

8 ViewChild,

9} от "@ angular / core";

10импорт {fromEvent} из "rxjs";

11импорт {фильтр} из "rxjs / операторов";

12 @ Component ({

13 селектор: "btn",

14 шаблон: `

15

16`,

17})

18export class ButtonComponent реализует AfterViewInit {

19 @ViewChild ("btn", {static: true}) el: ElementRef ;

20 @Output ("multiClick") multiClick = new EventEmitter ();

21 @Input ("requiredClicks") requiredClicks: number;

22

23 ngAfterViewInit () {

24 fromEvent (this.el.nativeElement, "click")

25 .pipe (filter ((value) => value.detail === this.requiredClicks))

26 .subscribe ((event) => {

27 this.multiClick .emit (событие);

28});

29}

30}

Сначала мы используем декоратор ElementRef и @ViewChild , чтобы получить доступ к элементу кнопки DOM. Затем в хуке ngAfterViewInit () , когда ссылка готова, мы обращаемся к ней и начинаем прослушивать события щелчка с помощью fromEvent () .Пропуская наблюдаемое через фильтр () , мы проверяем, соответствует ли количество щелчков (в свойстве детали ) требуемому количеству щелчков. Наконец, полученный наблюдаемый объект подписывается и при необходимости генерирует события.

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

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

 Копировать 

1

Преобразование горячего наблюдаемого в холодное

При обсуждении горячих и холодных наблюдаемых я сказал вам, что есть способ преобразовать холодное наблюдаемое в горячее.Это возможно благодаря некоторым сложным преобразованиям, которые можно использовать с помощью простого оператора share () .

 Копировать 

1импорт {интервал} из "rxjs";

2импорт из "rxjs / операторов";

3

4const наблюдаемый $ = interval (1000) .pipe (share ());

5

6observable $ .subscribe ((значение) => {

7 console.log («Подписка A», значение);

8});

9setTimeout (() => {

10 наблюдаемых $.subscribe ((значение) => {

11 console.log ("Подписка B", значение);

12});

13}, 2000);

14

15

16

17

18

19

20

21

22

Приведенный выше пример аналогичен тому, который мы проанализировали при обсуждении нескольких подписок на одно наблюдаемое. Обратите внимание на небольшую разницу - соединение оператора share () .

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

Обработка ошибок

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

Мы уже получили представление об этом с помощью наблюдателей в методе subscribe () и их обратного вызова error . Однако такой способ обработки ошибок имеет ряд серьезных недостатков. Во-первых, это конечный , что означает, что вы не сможете легко исправить ошибку, даже если захотите. Кроме того, это противоречит философии Angular разделения функций .

Существует специальный оператор, который может использоваться для обработки ошибок и решает обе эти проблемы - catchError () . Чтобы продемонстрировать его использование, давайте вызовем функцию создания fromFetch () :

 Копировать 

1import {fromFetch} из «rxjs / fetch»;

2import {catchError, retry} из "rxjs / operator";

3

4const observable $ = fromFetch ("/ example.json"). Pipe (

5 retry (3),

6 catchError (() => {

7 return Promise.решать([]);

8})

9);

Мы передаем retry () и catchError () в наш наблюдаемый объект fromFetch () . retry () - еще один полезный оператор, который повторно подпишется на исходный наблюдатель в случае ошибки и попытается запустить его до указанного количества повторных подписок.

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

В приведенном выше примере я возвращаю Promise.resolve ([]) в качестве «резервного значения» в случае ошибки. Это, в свою очередь, приведет к получению пустого массива в конце подписки при возникновении ошибки выборки, поскольку fromFetch () автоматически развернет обещание.

Этот краткий обзор должен дать вам общее представление о том, что такое catchError (), и другие операторы обработки ошибок. Они могут показаться здесь немного ненужными, но в более сложных сценариях с вложенными наблюдаемыми объектами, при использовании вместе с AsyncPipe или в других пограничных случаях они становятся бесценным .

Резюме

Этот подробный учебник по RxJS и FRP в Angular должен дать вам твердое представление об основах. Достаточно начать экспериментировать самостоятельно или перейти к изучению более сложных тем, таких как наблюдаемая вложенность, темы, планировщики или сложные операторы.

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

shiny Tutorial - reactive, reactiveValue и eventReactive, соблюдать ...

Введение

reactive, reactiveValue и eventReactive - это различные виды реактивных выражений в Shiny. Они дают результат, который можно использовать в качестве входных данных в других выражениях, которые, в свою очередь, будут зависеть от реактивного выражения.

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

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

реактивная

Можно использовать реактивную реакцию, чтобы сделать вывод зависимым от другого выражения. В приведенном ниже примере элемент output $ text зависит от text_reactive, который, в свою очередь, зависит от input $ user_text.Всякий раз, когда input $ user_text изменяется, output $ text element и text_reactive становятся недействительными . Они пересчитываются на основе нового значения для input $ user_text.

  библиотека (блестящая)

ui <- fluidPage (
  headerPanel ("Пример реактивного"),
  
  mainPanel (
    
    # поле ввода
    textInput ("user_text", label = "Введите текст:", placeholder = "Пожалуйста, введите текст."),
    
    # отображать вывод текста
    textOutput ("текст"))
)

server <- функция (ввод, вывод) {
  
  # реактивное выражение
  text_reactive <- реактивный ({
    введите $ user_text
  })
  
  # вывод текста
  output $ text <- renderText ({
    text_reactive ()
  })
}

shinyApp (пользовательский интерфейс = пользовательский интерфейс, сервер = сервер)
  

eventReactive

eventReactives аналогичны реактивам, они построены следующим образом:

  eventReactive (событие {
код для запуска
})
  

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

В приведенном ниже примере мы добавили кнопку отправки и создали eventReactive. Всякий раз, когда ввод $ user_text изменяется, eventReactive не становится недействительным, поскольку eventReactive зависит только от input $ submit actionButton. При каждом нажатии этой кнопки text_reactive и последующий вывод $ text становятся недействительными и будут пересчитаны на основе обновленного ввода $ user_text.

  библиотека (блестящая)

ui <- fluidPage (
  headerPanel ("Пример eventReactive"),
  
  mainPanel (
    
    # поле ввода
    textInput ("user_text", label = "Введите текст:", placeholder = "Пожалуйста, введите текст."),

    # кнопка отправки
    actionButton ("отправить", label = "Отправить"),
    
    # отображать вывод текста
    textOutput ("текст"))
)

server <- функция (ввод, вывод) {
  
  # реактивное выражение
  text_reactive <- eventReactive (input $ submit, {
    введите $ user_text
  })
  
  # вывод текста
  output $ text <- renderText ({
    text_reactive ()
  })
}

shinyApp (пользовательский интерфейс = пользовательский интерфейс, сервер = сервер)
  

реактивные значения

reactiveValues ​​может использоваться для хранения объектов, от которых могут зависеть другие выражения.

В приведенном ниже примере объект reactiveValues ​​инициализируется значением «Текст еще не отправлен». Создается отдельный наблюдатель для обновления объекта reactiveValues ​​при каждом нажатии кнопки отправки. Обратите внимание, что reactiveValues ​​не зависит от выражений в своем теле.

  библиотека (блестящая)

ui <- fluidPage (
  headerPanel ("Пример реактивных значений"),
  
  mainPanel (
    
    # поле ввода
    textInput ("user_text", label = "Введите текст:", placeholder = "Пожалуйста, введите текст."),
    actionButton ("отправить", label = "Отправить"),
    
    # отображать вывод текста
    textOutput ("текст"))
)

server <- функция (ввод, вывод) {
  
  # наблюдать событие для обновления reactiveValues
  Наблюдать за событием (вход $ представить,
               {
    text_reactive $ text <- ввод $ user_text
  })
  
  # reactiveValues
  text_reactive <- reactiveValues ​​(
    text = "Текст еще не отправлен."
  )
  
  # вывод текста
  output $ text <- renderText ({
    text_reactive $ text
  })
}

shinyApp (пользовательский интерфейс = пользовательский интерфейс, сервер = сервер)
  

наблюдать событие

Объект ObservationEvent может использоваться для запуска фрагмента кода при возникновении определенного события.Строится как:

  Наблюдать за событием (событие {
код для запуска
})
  

Наблюдение за событием будет зависеть только от раздела 'event' в небольшом фрагменте кода выше. Это не будет зависеть от чего-либо в части «код для запуска ». Пример реализации можно найти ниже:

  библиотека (блестящая)

ui <- fluidPage (
  headerPanel ("Пример реактивного"),
  
  mainPanel (
    
    # кнопки действий
    actionButton ("button1", "Button 1"),
    actionButton ("button2", "Button 2")
  )
)

server <- функция (ввод, вывод) {
  
  # Наблюдать за кнопкой 1 нажать.Наблюдать за событием (вход $ button1, {
    # Наблюдение за событием не зависит от кнопки 2, даже несмотря на то, что мы ссылаемся на ввод в следующей строке.
    ввод $ button2
    showModal (модальныйдиалог (
      title = "Кнопка нажата",
      "Вы нажали одну из кнопок!"
    ))
  })
}

shinyApp (пользовательский интерфейс = пользовательский интерфейс, сервер = сервер)
  

наблюдать

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

Также обратите внимание, что наблюдение не игнорирует NULL, поэтому оно будет срабатывать, даже если его входы по-прежнему равны NULL. Наблюдение за событием по умолчанию игнорирует NULL, что почти всегда желательно.

  библиотека (блестящая)

ui <- fluidPage (
  headerPanel ("Пример реактивного"),
  
  mainPanel (
    
    # кнопки действий
    actionButton ("button1", "Button 1"),
    actionButton ("button2", "Button 2")
  )
)

server <- функция (ввод, вывод) {
  
  # Наблюдать за кнопкой 1 нажать.наблюдать({
    input $ button1
    ввод $ button2
    showModal (модальныйдиалог (
      title = "Кнопка нажата",
      "Вы нажали одну из кнопок!"
    ))
  })
}

shinyApp (пользовательский интерфейс = пользовательский интерфейс, сервер = сервер)
  


MRR: Сделайте React Reactive. Функциональное программирование становится очень… | Николай Олексиенко

Функциональное программирование становится очень популярным среди разработчиков JavaScript.Однако, чтобы получить как можно больше от использования методов FP, библиотеки и инструменты, которые вы используете, должны иметь API, соответствующий функциональной парадигме. React использует функциональный подход для рендеринга DOM, но API состояния является обязательным и не «функционально дружественным». Redux считается функциональным, но наряду с редукторами (которые действительно функциональны) в реальном приложении вы, вероятно, будете иметь много асинхронных действий с большим количеством логики, что совсем не работает.

Mrr - это функциональная библиотека управления реактивным состоянием для React, которая позволяет раскрыть всю мощь функционального программирования. Основными преимуществами Mrr являются:

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

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

Например, в Mobx вы должны написать:

В Mrr это будет:

Функция, используемая для вычисления значений, не имеет доступа к состоянию, она принимает только некоторые аргументы. Это позволяет вам в большинстве случаев использовать чистые функции. Вы должны указать переменные, которые должны быть переданы в качестве аргументов функции. По умолчанию Mrr отслеживает зависимости и пересчитывает значение каждый раз, когда изменяется один из аргументов.

В Mrr вычисляемые переменные называются ячейками , как и ячейки Excel: их значения могут изменяться со временем и могут зависеть от значений других ячеек 'через формул (функции, используемые в исключениях Mrr, также называются формулами ) .В некоторых контекстах ячейки также упоминаются как потоки , поскольку они имеют разные значения с течением времени. Набор связанных ячеек называется сеткой .

Mrr разделяет девиз «Все есть поток», который позволяет записывать всю логику в виде набора взаимозависимых ячеек.

Рассмотрим типичный пример формы с двумя входами:

Вы создаете свой компонент, предоставляя конфигурацию Mrr и функцию рендеринга. Функция рендеринга похожа на функциональные компоненты React, но имеет другую сигнатуру: наряду с пропсами она также передает состояние , поскольку вычисляемые переменные Mrr устанавливаются в состояние.Помимо состояния и свойств, третий аргумент для функции рендеринга - это функция обратного вызова для создания обработчиков событий. Mrr рекомендует вам писать минималистичные обработчики событий, которые помещают в ячейку только какое-то значение (в этом случае также автоматически передают `e.target.value` в качестве значения для него), остальная логика должна выполняться в самих вычисляемых ячейках.

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

Ячейка пересчитывается каждый раз, когда изменяется одна из ее родительских ячеек. .
Итак, когда вы вводите первую букву во вход `name`,` nameValid` должно быть пересчитано и становится false , `formValid` также становится false .
Нам нужно, чтобы наша формула
`submitForm` запускалась после того, как пользователь нажимает` submit`, поэтому мы включили `submit` в ее список аргументов (хотя мы опускаем его в аргументах формулы, поскольку на самом деле нам не важно его значение) .

Проблема в том, что он также будет запускаться при изменении ячеек `formValid`,` name` или `emails`, так как они также являются его аргументами!
Мы можем исправить это с помощью механизма под названием пассивное прослушивание :

Добавление минуса перед именем ячейки позволяет вам не реагировать на ее изменения, сохраняя при этом ее значение в качестве аргумента в формуле.Теперь ячейка submitForm будет пересчитываться только при изменении ячейки submit. В этом случае ячейка «submit» считается ячейкой сигнала , а «formValid» и другие ячейки - это ячейки со значением и .

Значения и сигналы

Обычно используемая модель «вычисляемых переменных» - это только половина реактивного подхода - часть, которую я называю «реактивностью на основе значений» (типичный пример - вычисление полного имени). Другая половина - это «реактивность на основе сигналов».

Как и в случае с ячейкой «submit», иногда нас фактически не волнуют значения потока, но порядок событий во времени имеет решающее значение - вот о чем говорят сигналы.Mrr сочетает в себе оба подхода с мощным, но простым синтаксисом.

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

Рассмотрим следующий пример: нам нужно открывать всплывающее окно при нажатии и закрывать его при щелчке по другому элементу.

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

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

Давайте немного реорганизуем наш код:

Мы называем это объединение потоков , поскольку несколько потоков объединяются в один поток.

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

Здесь мы видим, что потоки `error` и` submitForm` зависят от одного и того же сигнала - `submit`, хотя другие зависимости немного отличаются.

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

Async

Работать с асинхронностью в Mrr легко и весело. Просто не имеет значения, является ли ваша формула синхронной или асинхронной!
Давайте добавим некоторую внутреннюю проверку для нашего ввода:

Вы можете просто вернуть обещание как результат формулы, и Mrr установит значение в ячейку по мере ее разрешения! Вы также можете использовать функции ES8 async без дополнительных усилий.

Но что, если нам нужно обрабатывать ошибки или отслеживать, выполняется ли запрос API?
Оператора разделения здесь недостаточно, так как нам нужно поместить значения в разные подъячейки , выполняя единственную формулу (вызов ajax). В этом случае Mrr имеет, ну, более императивный оператор, называемый вложенным .

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

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

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

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

Обратите внимание, что мы дважды помещаем значения в подъячейку «загрузка».Фактически, мы можем делать это сколько угодно раз. Например:

Отслеживание того, загружается ли запрос, позволяет нам отключить кнопку «отправить».

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

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

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