Русский
Русский
English
Статистика
Реклама

Шизофрения

Фрактальная шизофрения

30.08.2020 00:09:30 | Автор: admin


Нет, я не болен. По крайней мере так говорит голос в моей голове. Я наркоман. Вот уже более 15 лет я сижу на игле. Употребляю много, жёстко, до оборочного состояния. Докатился до того, что в последнее время не стесняюсь ни друзей, ни жены, ни детей Двоих детей! Не люблю бадяженый, люблю чистый, без примесей. За годы перепробовал многое, но в последнее время остановился в поисках. Забавно осознавать, что от одного и того же получаешь одновременно и боль, и радость. Мне бы в лечебку, я даже хочу, я даже знаю в какую. Знаете такие, где продолжаешь употреблять, но под присмотром?


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


Помню тот день, когда узнал о новой es-фишке генераторах и итераторах. Я только пересел с ruby на javascript, втянулся в него, как в голове что-то щёлкнуло а как же yield? Восторгу не было предела! Он есть, да ещё и работает по другому это что ж получается: можно код останавливать? можно возобновлять? а ещё и параметры по ходу выполнения вводить/выводить? Oh My God!


Теперь я пихал их везде. Извращался над ними, как мог, чувствовал в них что-то магическое, не понимал, что именно, но банальная генерация бесконечных коллекций казалась лишь вершиной айсберга их функционала. Посему упорно раз за разом я пытался вывернуть их наизнанку, ставил опыты, как, например, yield первого подать на ввод второго и обратно yield второго подать на ввод первого, зациклить, да ещё и какой-то КПД с этого получить. В общем изголялся настолько, насколько фантазии хватало. В какой-то момент идеи закончились, все подопытные были замучены насмерть, новый гибрид вывести не удалось...


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


Взгляды на фронтенд-разработку довольно сильно разнились с текущими трендами. Принципы MV* казались, не то что притянутыми вытянутыми за уши с сервера в браузер. Чёрт возьми да мы до сих пор с третьей буквой * определиться не можем! А стейт? Мы слепо верим, что скелет M должен висеть в шкафу, а плоть V лежать на полке и чем дальше друг от друга тем лучше, при этом оба должны обмениваться приветами и хлопать в ладоши, потому что нам лучше знать, как вам лучше жить!


С этими мыслями я вернулся в лабораторию генераторов, а заодно перешёл на typescript. Человек я разносторонний, попав в википедию, переходами по ссылкам могу погружаться в глубь стека до заветного Maximum call stack size exceeded с последующей потерей контекста и вопросом типа а чё меня сюда вообще понесло? Собственно эта разностороность сначала добавила в список моих интересов астрономию, квантовую механику и теорию эфира, а затем труды Бенуа Мандельброта и, соответственно, фракталы.


Я помешался. Сознание будто трансформировалось. Отныне во всём я искал и находил фрактальную составляющую, в программном коде, в грамматиках парсеров. Html-код это же фрактал, разве нет? Почему бы не сделать всё приложение фракталом? А результат? Мы разрабатываем программу, для того чтобы получить от нее ожидаемый результат, а то и серию результатов последовательность кадров отрисовки на экране, сообщений в логе консоли а ведь это по сути контрольные точки во времени её жизни поток отражений её состояния в ходе выполнения, дающий возможность представить происходящее внутри...


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


Безумные идеи а-ля "наш мир один большой фрактал" то и дело теребили разум и не только мой я задолбал этими разговорами жену и друзей, дети, к их счастью, не попадали под эту раздачу отборного бреда. Однажды я заявил супруге: "Заведу себе пса, назову Фрактал" долго смеялись "Фрактал! Ко мне!". Звучит! Не правда ли?)


Как-то февральским вечером я стоял на балконе и втыкал в звёзды. Небо на удивление было необычайно чистым. Сириус, самая яркая, всегда в это время висящая над крышей дома напротив, казалось, была близка, как никогда. А что если рвануть навстречу звезде? И, чисто гипотетически что если, во время приближения, с определенного расстояния мы обнаружим, что это не звезда, а целое созвездие или система звёзд? Ведь с Сириусом так и было до середины 19 века считалось, что это самостоятельная звезда, пока в 1844 немецкий астроном Фридрих Бессель не предположил, а в 1862 американский астроном Альван Кларк не подтвердил, что Сириус это система из двух звёзд, вращающихся вокруг общего центра масс. Впоследствии они получили названия Сириус А и Сириус В. Две близко расположенных звезды, свет которых ввиду огромного расстояния воспринимается нами, как излучаемый одним источником. А что если выбрать одну из этих звёзд и лететь уже навстречу ей, а с какого-то расстояния опять обнаружить созвездие? А что если так будет повторяться бесконечно? Мы бесконечно будем видеть поток света, проецируемый на сетчатку нашего глаза, но при всём желании не сможем достичь его источника, а именно так и получается при постоянном погружении во множество Мандельброта, Жулиа Мы постоянно видим Поток? Проекций? Фрактала?


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


Должен признаться, что на сбор этого паззла ушло несколько месяцев, 3 репозитория, ~800 git-веток и тысячи строк экспериментального кода. Теперь мне не давал покоя yield*. Да-да, со звёздочкой. Вы часто используете return внутри генератора? С вашего позволения я разбавлю этот эпос небольшим куском кода, в котором, используя генераторы, мы опишем формирование проекции Сириуса в созвездии Большого Пса.


async function* SiriusA() {    return '*A' // Проекция звезды Сириус А}async function* SiriusB() {    return '*B' // Проекция звезды Сириус В}async function* Sirius() {    // ['*A', '*B'] Проекция звёздной системы Сириус    return [yield* SiriusA(), yield* SiriusB()]}async function* CanisMajor() {    const sirius = yield* Sirius() // ['*A', '*B']    // а где-то тут создается проекция созвездия Большого Пса}

И так до бесконечности можно собирать всё более и более сложные структуры-проекции. Вы скажете: "Что тут особенного? Все тоже самое можно описать обычными функциями" и будете правы, но одна особенность тут всё же есть. Вся фишка в yield*. Дело в том, что на пути следования к return-значению данное выражение попутно будет "выкидывать наверх" встречающиеся yield-значения, что можно задействовать в служебных целях скрытно, за кулисами, определить контекст выполнения, режим работы и прочие внутренние системные параметры. Не буду утомлять вас подробностями реализации на самом деле, как сказал Йозеф Геббельс: "Всё гениальное просто", а все мои танцы с бубном в итоге вылились в ~300 строк элементарного кода. Нет я не гений, это самокритика, из-за которой какое-то время я чувствовал себя идиотом, ведь как оказалось решение лежало на поверхности, нужно было лишь взглянуть под нужным углом. Видать угол долго искал.


Всё есть фрактал


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


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



@fract/core это реализация небольшая библиотека, предоставляющая два простых строительных блока: fractal и fraction. С их помощью можно описать сколь угодно сложную я надеюсь структуру, которая будет являться фрактальным приложением. Последнее можно запустить в браузере или на сервере, а можно упаковать в библиотеку, поделиться ею в npm и подключить через yield*.


Простой фрактальный Hello world может выглядеть, например, так


import { fractal, fraction } from '@fract/core'const Title = fraction('Hello world')const HelloWorld = fractal(async function* () {    while (true) yield `App: ${yield* Title}`})

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


Жизненный цикл


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



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


  1. с помощью генератора создается новый итератор
  2. итератор выполняется до ближайшего yield или return полученное значение будет принято за текущую проекцию, во время этой работы все вызовы yield* автоматически устанавливают наблюдаемые зависимости; как только новая проекция сгенерирована, фрактал переходит в режим ожидания обновлений, а вышестоящий фрактал узнаёт об изменениях
  3. узнав об изменениях в нижестоящих фракталах, список зависимостей очищается и, если на предыдущем шаге проекция была получена с помощью yield, фрактал продолжает свою работу со второго шага; если же был return работа продолжается с первого шага

Таким образом return делает то же самое, что и yield определяет текущую проекцию, но при этом происходит "перезагрузка" и всё начинается с начала.


Проекции и потоки


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


Обычный фрейм соответствует следующему интерфейсу и содержит в себе текущую проекцию фрактала


interface Frame<T> {    data: T;}

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


interface LiveFrame<T> extends Frame<T> {    next: Promise<LiveFrame<T>>;}

Живой фрейм это и есть тот самый поток проекций фрактала, иными словами: последовательность снимков его состояния.


Методы запуска


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


import { exec, live } from '@fract/core'

exec<T>(target: Fractal<T> | AsyncGenerator<T>): Promise<Frame<T>>


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


const frame = await exec(HelloWorld)frame.data // 'App: Hello world'

live<T>(target: Fractal<T> | AsyncGenerator<T>): Promise<LiveFrame<T>>


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


const frame = await live(HelloWorld)frame.data // 'App: Hello world'Title.use('Fractal Demo')const nextFrame = await frame.nextnextFrame.data // 'App: Fractal Demo'

Фрактальное приложение


Опишем фрактал некоторого пользователя, имеющего имя, возраст и банковскую карту


const Name = fraction('John')const Age = fraction(33)const Balance = fraction(100)const Card = fractal(async function* () {    while (true) {        yield {            balance: yield* Balance,        }    }})const User = fractal(async function* () {    while (true) {        yield {            name: yield* Name,            age: yield* Age,            card: yield* Card,        }    }})

Каждый описанный выше фрактал является полноценным приложением и может входить в состав более сложных фракталов


const frame = await exec(Balance)frame.data //> 100

const frame = await exec(Card)frame.data //> {balance: 100}

const frame = await exec(User)frame.data/*> {    name: 'John',    age: 33,    wallet: {        balance: 100    }}*/

С помощью exec получаются разовые снимки текущего состояния, а с помощью live живые


const frame = await live(User)console.log(frame.data)/*> {    name: 'John',    age: 33,    card: {        balance: 100    }}*/Name.use('Barry')Balance.use(200)const nextFrame = await frame.nextconsole.log(nextFrame.data)/*> {    name: 'Barry',    age: 33,    card: {        balance: 200    }}*/

Чтобы получать живые проекции и не заниматься перебором цепочки фреймов, можно написать фрактал, который будет передавать проекцию от User потребителю (выводить в консоль например), а в качестве своей отдавать undefined (выше всё равно уже никого нет)


const App = fractal(async function* () {    while (true) {        console.log(yield* User)        yield    }})live(App) // запускаем приложение

Именование


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


const User = fractal(async function* _User() {    /*...*/})User.name // '_User'

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


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



const user = yield* User

Реактивность


Система реактивности фрактала сама по себе фрактал, по своей структуре напоминающий фрактал Кантора



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


В каждом живом фрейме промис следующего фрейма является по сути, промисом актуальности текущей проекции, пока он не зарезолвился проекция жива. Список зависимостей, собираемый на втором шаге жизненного цикла, это массив таких промисов Promise<LiveFrame<T>>[], именуемый racers, когда он составлен, создается гонка Promise.race(racers) эта гонка тоже промис racer текущей проекции, и в вышестоящем фрактале он опять попадает в массив racers петля замыкается. Визуально это можно выразить так



То же самое в коде будет выглядеть следующим образом



Promise.race([    // level 1     Promise.race([/* ... */]),    Promise.race([/* ... */]),    Promise.race([        // level 2        Promise.race([/* ... */]),        Promise.race([/* ... */]),        Promise.race([/* ... */]),        Promise.race([/* ... */]),        Promise.race([/* ... */]),         Promise.race([             // level 3            Promise.race([/* ... */]),            Promise.race([/* ... */])         ])    ])])

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


const Name = fraction('John')const User = fractal(async function* () {    while (true) {        yield `User ${yield* Name}`    }})const Title = fraction('Hello')const Post = fractal(async function* () {    while (true) {        delay(5000) // что-то долго делаем        yield `Post ${yield* Title}`    }})const App = fractal(async function* () {    while (true) {        console.log(`App | ${yield* User} | ${yield* Post}`)        yield    }})live(App)//> 'App | User John | Post Hello'Name.use('Barry')Title.use('Bye')//> 'App | User Barry | Post Hello'// через 5 секунд//> 'App | User Barry | Post Bye'

Здесь мы одновременно внесли изменения во фракции Name и Title, после чего фракталы User и Post начинают обновлять свои проекции, User сделает это первым, затем App обновится не дожидаясь обновления Post на самом деле App вообще не знает, что Post сейчас обновляется. App обновится ещё раз после того, как Post завершит работу над своей новой проекцией. Ключевой момент тут в том, что один медленный фрактал не "вешает" работу всего приложения.


Временные проекции


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


Один из вариантов использования организация "лоадеров". Работая во фронтенде, я всегда люто ненавидел лепить эти крутилки-вертелки, хотя понимал их необходимость.


import { fractal, tmp } from '@fract/core'const User = fractal(async function* () {    yield tmp('Loading...')    delay(5000) // что-то долго делаем    while (true) {        yield `User John`    }})const App = fractal(async function* () {    while (true) {        console.log(yield* User)        yield    }})live(App)//> 'Loading...'// через 5 секунд//> 'User John'

Здесь фрактал User является "медленным", прежде чем отдать свою проекцию ему надо сходить на сервер, по пути зайти в магазин и т.д. А кто-то сверху в это время ждёт его проекцию. Так вот, чтобы не заставлять себя ждать User отдаёт временную проекцию 'Loading...' и продолжает генерировать основную, которую отдаст по мере готовности, т.е. код генератора после yield tmp(...) продолжает выполняться, но уже в фоне.


Это ещё не всё вот так, например, можно сделать фрактал-таймер


import { fractal, tmp } from '@fract/core'const Timer = fractal(async function* () {    let i = 0    while (true) {        yield tmp(i++)        await new Promise((r) => setTimeout(r, 1000))    }})const App = fractal(async function* () {    while (true) {        console.log(yield* Timer)        yield    }})live(App)//> 0//> 1//> 2//> ...

Здесь фрактал Timer отдаёт текущее значение переменной i в качестве своей временной проекции и продолжает вычисление следующей, в процессе чего инкрементит i, дожидается окончания задержки в 1 секунду и цикл повторяется. Кстати говоря фракция именно так и устроена она отдаёт временную проекцию с текущим значением, и ждёт завершения промиса, который зарезолвится новым значением переданным в метод .use(data), после чего цикл повторится.


Делегирование


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


Допустим у нас есть фабрика newEditor, которая создает фрактал, отвечающий за редактирование профиля пользователя. Также у нас есть фрактал Manager, который в зависимости от фракции ProfileId переключает редактируемый профиль.



function newEditor(id) {    return fractal(async function* () {        const { name } = await loadUserInfo(id)        const Name = fraction(name)        while (true) {            // где-то в глубине этого фрактала генерируется            // интерфейс редактирования имени пользователя            yield <input                 placeholder="Input name"                 value={yield* Name}                 onChange={(e) => Name.use(e.target.value)}             />        }    })}const ProfileId = fraction(1)const Manager = fractal(async function* () {    while (true) {        const id = yield* ProfileId        const Editor = newEditor(id)        yield Editor // <-- делегируем работу фракталу Editor    }})const App = fractal(async function* () {    while (true) {        yield yield* Manager    }})

Фрактальное дерево будет производить пересборку проекций изнутри-наружу каждый раз, когда где-то в его глубине при редактировании будут происходить изменения, в данном примере во фракции Name. Пересборка неизбежно будет перезапускать циклы while(true) на всех уровнях до самого корня App, за исключением фрактала Manager. Последний делегирует работу над своей проекцией фракталу Editor, и как бы выталкивается из цепочки регенерации.



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


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


const ProfileId = fraction(1)const Manager = fractal(async function* () {    let lastProfileId    let Editor    while (true) {        const id = yield* ProfileId        if (id !== lastProfileId) {            lastProfileId = id            Editor = newEditor(id)        }        yield yield* Editor    }})

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


const BarryName = fractal(async function* () {    while (true) yield 'Barry'})const Name = fraction('John')const App = fractal(async function* () {    while (true) {        console.log(yield* Name)        yield    }})live(App)//> 'John'Name.use(BarryName)//> 'Barry'

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


Факторы


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



import { factor } from '@fract/core'const API_VERSION = factor('v2') // 'v2' | 'v3'// необязательное значение ^^^^ по умолчанию/* далее код из тела генератора */yield* API_VERSION('v3')    // устанавливаем значение фактораyield* API_VERSION          // 'v3' - получаемyield* API_VERSION.is('v3') // boolean - сравниваем// установка без аргументов эквивалентна// сброcу до значения по умолчаниюyield* API_VERSION()yield* API_VERSION          // 'v2' 

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


const Page = fractal(async function* () {    const apiVersion = yield* API_VERSION    while (true) {        yield `Work on api "${apiVersion}"`    }})const Modern = fractal(async function* () {    yield* API_VERSION('v3')    // всем нижележащим фракталам изпользовать api v3    while (true) {        yield yield* Page    }})const Legacy = fractal(async function* () {    yield* API_VERSION('v2')    // всем нижележащим фракталам изпользовать api v2    while (true) {        yield yield* Page    }})const App = fractal(async function* () {    while (true) {        console.log(`            Modern: ${yield* Modern}            Legacy: ${yield* Legacy}        `)        yield    }})live(App)/*> `    Modern: Work on api "v3"    Legacy: Work on api "v2"`*/

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



const Top = fractal(async function* () {    yield* API_VERSION('v3')    while (true) {        yield yield* Middle    }})const Middle = fractal(async function* () {    yield* API_VERSION       // 'v3' - определено во фрактале Top    yield* API_VERSION('v2') // переопределяем, но для нижних уровней    yield* API_VERSION       // на своем уровне у нас остается 'v3'    while (true) {        yield yield* Bottom    }})const Bottom = fractal(async function* () {    yield* API_VERSION       // 'v2' - переопределено в Middle    while (true) {        yield /*...*/    }})

И кость и плоть


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



const APP_STORE = 'APP'function newApp({ name = 'Hello world' } /* AppState {name: string} */) {    const Name = fraction(name)    return fractal(async function* App() {        while (true) {            switch (yield* MODE) {                case 'asString':                    yield `App ${yield* Name}`                    continue                case 'asData':                    yield { name: yield* Name } // as AppState {name: string}                    continue            }        }    })}const Dispatcher = fractal(async function* () {    // берем сохраненное состояние из локального хранилища    const data = JSON.parse(localStorage.getItem(APP_STORE) || '{}')    // создаем фрактал нашего приложения    const App = newApp(data)    // создаем фрактал с предопределенным режимом работы 'asString'    const AsString = fractal(async function* () {        yield* MODE('asString')        while (true) yield yield* App    })    // создаем фрактал с предопределенным режимом работы 'asData'    const AsData = fractal(async function* () {        yield* MODE('asData')        while (true) yield yield* App    })    while (true) {        const asString = yield* AsString // это мы выведем на экран        const asData = yield* AsData     // а это сохраним в хранилище        // выводим        console.log(asString)        // сохранияем        localStorage.setItem(APP_STORE, JSON.stringify(asData))        yield    }})

Что тут происходит: один и тот же фрактал App по разному генерирует свои проекции в зависимости от фактора MODE, зная это мы подключаем его к фракталам AsString и AsData, которые в свою очередь подключаем к Dispatcher. В результате мы получаем две разных проекции, принадлежащих одному и тому же фракталу одна в текстовом виде, вторая в виде данных.



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


MV* MVVM MVP


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



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


Фрактальный модуль


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


import { fractal, factor } from '@fract/core'// app.jsexport const API_URI = factor()export const THEME = factor('light')export const App = fractal(async function* () {    const apiUri = yield* API_URI    const theme = yield* THEME    if (!apiUri) {        // обязательный фактор        throw new Error('Factor API_URI is not defined')    }    while (true) {        /*...*/    }})

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


Асинхронность и code splitting


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


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



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


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


// ./user.jsexport const User = fractal(async function* () {    while (true) yield `User John`})// ./app.jsexport const App = fractal(async function* () {    // импортируем зависимость, когда она нам действительно нужна    const { User } = await import('./user')    while (true) yield `User ${yield* User}`})

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


Смотри вглубь


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


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


После усвоения этого правила, демка была написана довольно быстро. В азарте от гордости за проделанную работу я написал ещё парочку, чтоб придти сюда не с пустыми руками. Все они написаны с использованием react и styled-components это привычные для меня элементы стека разработки и надеюсь, что их присутствие не повлияет на ваше восприятие, поскольку использованы они исключительно в целях визуализации.


  • Todos думаю этот пример не нуждается в представлении
  • Loadable пример, показывающий работу временных проекций, в исходниках можно увидеть, как с помощью yield tmp(...) организуется показ лоадеров в то время, как в фоне производится загрузка, я специально добавил там небольшие задержки для того, чтоб немного замедлить процессы
  • Factors работа в разных условиях. Один и тот же фрактал в зависимости от установленного в контексте фактора отдаёт три разные проекции, а также поддерживает их актуальность. Попробуйте поредактировать имя и возраст.
  • Antistress просто игрушка, щёлкаем шарики, красим их в разные цвета и получаем прикольные картинки. По факту это фрактал, который показывает внутри себя кружок, либо три таких же фрактала вписанных в периметр круга. Клик покрасить, долгий клик раздавить, долгий клик в центре раздавленного кружка возврат в исходное состояние. Если раздавить кружки до достаточно глубокого уровня, можно разглядеть треугольник Серпинского

Планы на будущее


  • попробовать внедрить возможность использования синхронных генераторов для повышения производительности в тех местах приложения, где асинхронность не требуется
  • написать рендер jsx -> html заточенный именно под фрактальную структуру, react годится только для демок, ибо по факту вся его работа заключается только в том, чтобы вычислить diff и применить изменения, остальной код простаивает
  • а может даже рассмотреть вариант создания собственной фрактальной системы компонентов и их стилизации амбициозно не правда ли? ещё амбициознее то, что браузер также может быть фракталом, как и другие приложения операционной системы, как и сама операционная система в целом
  • поэкпериментировать с grahpql, где-то на горизонте мне мерещится элегантное решение с организацией подписок на события сервера а-ля yield* gql'...'
  • связать свою жизнь с open source это и есть та самая лечебка, о которой я говорил в самом начале
  • выучить английский :) Кстати, поскольку у меня с ним сейчас трудности буду рад любой помощи по переводу и дополнению readme

Попробовать


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


Разрабатывать сейчас коммерческий продукт с нуля на фрактале я бы не рекомендовал, всё таки пока что это в первую очередь идея и концепт, требующий ухода и заботы для правильного роста во что-то зрелое, а вот попробовать где-то на кусочке своего react-приложения можно, для этого я создал простой компонент и оформил его ввиде библиотеки @fract/react-alive


import { fractal } from '@fract/core'import { Alive } from '@fract/react-alive'const App = fractal(async function* () {    while (true) {        yield <div>Hello world</div>    }})function Render() {    return <Alive target={App} />}

Насчёт библиотек я говорил, что можно создать фрактальное приложение, упаковать его в библиотеку и подключить через yield*? В качестве примера я сделал библиотеку @fract/browser-pathname. Она экспортирует фрактал, проекцией которого является параметр window.location.pathname, и метод redirect(p: string) позволяющий его менять. Её исходники находятся тут, а то, как с её помощью можно организовать простейший роутер, можно увидеть в исходниках главной демо-страницы.


Напоследок


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



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


С уважением, Денис Ч.


"Большая часть моих трудов это муки рождения новой научной дисциплины" Бенуа Мандельброт

Подробнее..

Фрактальная шизофрения. Whats up?

01.04.2021 04:04:20 | Автор: admin


По некоторым источникам еще в IV до нашей эры Аристотель задался одним простым вопросом Что было раньше? Курица или яйцо? Сам он в итоге пришел к выводу, что и то, и другое появилось одновременно вот это поворот! Не правда ли?


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


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


Сегодня я не буду терзать ваш разум водопадом отборного бреда. Выпуск будет чуть суровее ибо лирики меньше, а кода больше. Тем не менее местами он будет вкуснее ибо вишенки я вам приготовил отменные. Поехали?


What's up guys?


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


npm i whatsup

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


Построен он на генераторах, из коробки даёт функционал аналогичный react + mobx, не уступает по производительности, при этом весит менее 5kb gzip.


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


Cause & Conse


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


Начнём со следствия. По сути это одноимённая причина, которой из вне можно задавать значение возвращаемого следствия (маслянистое определение получилось, но чисто технически всё так и есть).


const name = conse('John')// И мы ему такие - What`s up name?whatsUp(name, (v) => console.log(v))// а он нам://> "John"name.set('Barry')//> "Barry"

Пример на CodeSandbox


Ничего особенного, правда? conse создает поток с начальным значением, whatsUp "вешает" наблюдателя. С помощью .set(...) меняем значение наблюдатель реагирует в консоли появляется новая запись.


На самом деле Conse это частный случай потока Cause. Последний создается из генератора, внутри которого выражение yield* это "подключение" стороннего потока к текущему, иными словами обстановку внутри генератора можно рассмотреть так, как будто бы мы находимся внутри изолированной комнаты, в которую есть несколько входов yield* и всего один выход return (конечно же yield ещё, но об этом позже)


const name = conse('John')const user = cause(function* () {    return {        name: yield* name,        //    ^^^^^^ подключаем поток name        //           пускаем его данные в комнату    }})// И мы ему такие - What`s up user? :)whatsUp(user, (v) => console.log(v))// а он нам://> {name: "John"}name.set('Barry')//> {name: "Barry"}

Пример на CodeSandbox


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


И в чем тут соль генераторов?


Действительно, пока что всё это выглядит как-то необоснованно "стероидно". Давайте немного усложним наш пример. Представим, что в данных потока user мы хотим видеть некоторый дополнительный параметр revision, отражающий текущую ревизию.


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


const name = conse('John')let revision = 0const user = cause(function* () {    return {        name: yield* name,        revision: revision++,    }})whatsUp(user, (v) => console.log(v))//> {name: "John", revision: 0}name.set('Barry')//> {name: "Barry", revision: 1}

Пример на CodeSandbox


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


const name = conse('John')const user = cause(function* () {    let revision = 0    while (true) {        yield {            name: yield* name,            revision: revision++,        }    }})whatsUp(user, (v) => console.log(v))//> {name: "John", revision: 0}name.set('Barry')//> {name: "Barry", revision: 1}

Пример на CodeSandbox


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


Расширенный пример


Функции cause и conse это шорты для создания потоков. Существуют одноименные базовые классы, доступные для расширения.


import { Cause, Conse, whatsUp } from 'whatsup'type UserData = { name: string }class Name extends Conse<string> {}class User extends Cause<UserData> {    readonly name: Name    constructor(name: string) {        super()        this.name = new Name(name)    }    *whatsUp() {        while (true) {            yield {                name: yield* this.name,            }        }    }}const user = new User('John')whatsUp(user, (v) => console.log(v))//> {name: "John"}user.name.set('Barry')//> {name: "Barry"}

Пример на CodeSandbox


При расширении нам необходимо реализовать метод whatsUp, возвращающий генератор.


Контекст и диспозинг


Единственный агрумент принимаемый методом whatsUp является текущий контекст. В нём есть несколько полезных методов, один из которых update позволяет принудительно инициировать процедуру обновления.


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


Рассмотрим пример потока-таймера, который с задержкой в 1 секунду, используя setTimeout, генерирует новое значение, а при уничтожении вызывает clearTimeout для очистки таймаута.


const timer = cause(function* (ctx: Context) {    let timeoutId: number    let i = 0    try {        while (true) {            timeoutId = setTimeout(() => ctx.update(), 1000)            // устанавливаем таймер перезапуска с задержкой 1 сек            yield i++            // отправляем в поток текущее значение счетчика            // заодно инкрементим его        }    } finally {        clearTimeout(timeoutId)        // удаляем таймаут        console.log('Timer disposed')    }})const dispose = whatsUp(timer, (v) => console.log(v))//> 0//> 1//> 2dispose()//> 'Timer disposed'

Пример на CodeSandbox


Мутаторы всё из ничего


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


const increment = mutator((i = -1) => i + 1)const timer = cause(function* (ctx: Context) {    // ...    while (true) {        // ...        // отправляем мутатор в поток        yield increment    }    // ...})

Пример на CodeSandbox


Мутатор устроен очень просто это метод, который принимает предыдущее значение и возвращает новое. Чтобы он заработал нужно всего лишь вернуть его в качестве результата вычислений, вся остальная магия произойдет под капотом. Поскольку при первом запуске предыдущего значения не существует, мутатор получит undefined, параметр i по умолчанию примет значение -1, а результатом вычислений будет 0. В следующий раз ноль мутирует в единицу и т.д. Как вы уже заметили increment позволил нам отказаться от хранения локальной переменной i в теле генератора.


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


class EqualArr<T> extends Mutator<T[]> {    constructor(readonly next: T[]) {}    mutate(prev?: T[]) {        const { next } = this        if (            prev &&             prev.length === next.length &&             prev.every((item, i) => item === next[i])        ) {            /*            Возвращаем старый массив, если он эквивалентен новому,             планировщик сравнит значения, увидит,             что они равны и остановит бессмысленные пересчеты            */            return prev        }        return next    }}const some = cause(function* () {    while (true) {        yield new EqualArr([            /*...*/        ])    }})

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


Также как cause и conse функция mutator это шорт для краткого определения простого мутатора. Более сложные мутаторы можно описать, расширяя базовый класс Mutator, в котором необходимо реализовать метод mutate.


Смотрите вот так можно создать мутатор dom-элемента. И поверьте элемент будет создан и вставлен в body однократно, всё остальное сведётся к обновлению его свойств.


class Div extends Mutator<HTMLDivElement> {    constructor(readonly text: string) {        super()    }    mutate(node = document.createElement('div')) {        node.textContent = this.text        return node    }}const name = conse('John')const nameElement = cause(function* () {    while (true) {        yield new Div(yield* name)    }})whatsUp(nameElement, (div) => document.body.append(div))/*<body>    <div>John</div></body>*/name.set('Barry')/*<body>    <div>Barry</div></body>*/

Пример на CodeSandbox


Так это ж стейт менеджер на генераторах


Да с одной стороны WhatsUp это стейт менеджер на генераторах, в нём есть аналоги привычных observable, computed, reaction. Есть и action, позволяющий внести несколько изменений и провести обновление за один проход. Пока что ничего необычного, но то что вы увидите дальше, выгодно отличает его от других систем управления состоянием.


Фракталы


Я же говорил, что сохранил идею :) Особенность фрактала заключается в том, что для каждого потребителя он создает персональный генератор и контекст. Он как по лекалу создает новую, параллельную вселенную, в которой своя жизнь, но те же правила. Контексты соединяются друг с другом в отношения parent-child получается дерево контекстов, по которому организуется спуск данных вниз к листьям и всплытие событий вверх к корню. Контекст и система событий, Карл! Пример ниже длинный, но наглядно демонстрирует и то, и другое.


import { Fractal, Conse, Event, Context } from 'whatsup'import { render } from '@whatsup/jsx'class Theme extends Conse<string> {}class ChangeThemeEvent extends Event {    constructor(readonly name: string) {        super()    }}class App extends Fractal<JSX.Element> {    readonly theme = new Theme('light');    readonly settings = new Settings()    *whatsUp(ctx: Context) {        // расшариваем поток this.theme для всех нижележащих фракталов        // т.е. "спускаем его" вниз по контексту        ctx.share(this.theme)        // создаем обработчик события ChangeThemeEvent, которое можно        // инициировать в любом нижележащем фрактале и перехватить тут        ctx.on(ChangeThemeEvent, (e) => this.theme.set(e.name))        while (true) {            yield (<div>{yield* this.settings}</div>)        }    }}class Settings extends Fractal<JSX.Element> {    *whatsUp(ctx: Context) {        // берем поток Theme, расшаренный где-то в верхних фракталах        const theme = ctx.get(Theme)        // инициируем всплытие события, используя ctx.dispath        const change = (name: string) =>             ctx.dispath(new ChangeThemeEvent(name))        while (true) {            yield (                <div>                    <h1>Current</h1>                    <span>{yield* theme}</span>                    <h1>Choose</h1>                    <button onClick={() => change('light')}>light</button>                    <button onClick={() => change('dark')}>dark</button>                </div>            )        }    }}const app = new App()render(app)

Пример на CodeSandbox


Метод ctx.share используется для того, чтобы сделать экземпляр какого-то класса доступным для фракталов стоящих ниже по контексту, а вызов ctx.get с конструктором этого экземпляра позволяет нам найти его.


Метод ctx.on принимает конструктор события и его обработчик, ctx.dispatch в свою очередь принимает инстанс события и инициирует его всплытие вверх по контексту. Для отмены обработки события существует ctx.off, но в большинстве случаев им не приходится пользоваться, поскольку все обработчики уничтожаются автоматически при уничтожении генератора.


Я настолько заморочился, что написал свой jsx-рендер и babel-плагин для трансформации jsx-кода. Уже догадываетесь что под капотом? Да мутаторы. Принцип тот же, что и в примере с мутатором dom-элемента, только тут создается и в дальнейшем мутируется определенный фрагмент html-разметки. Создания и сравнения всего виртуального dom (как в react, например) не происходит. Всё сводится к локальным пересчетам, что даёт хороший прирост в производительности. Иными словами в примере выше, при изменении темы оформления, перерасчеты и обновление dom произойдут только во фрактале Settings (потому что yield* theme поток подключен только там).


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


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


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


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


import { conse, Fractal } from 'whatsup'import { render } from '@whatsup/jsx'class CounterMoreThan10Error extends Error {}class App extends Fractal<JSX.Element> {    *whatsUp() {        const clicker = new Clicker()        const reset = () => clicker.reset()        while (true) {            try {                yield (<div>{yield* clicker}</div>)            } catch (e) {                // ловим ошибку, если "наша" - обрабатываем,                // иначе отправляем дальше в поток и даем возможность                 // перехватить её где-то в вышестоящих фракталах                if (e instanceof CounterMoreThan10Error) {                    yield (                        <div>                            <div>Counter more than 10, need reset</div>                            <button onClick={reset}>Reset</button>                        </div>                    )                } else {                    throw e                }            }        }    }}class Clicker extends Fractal<JSX.Element> {    readonly count = conse(0)    reset() {        this.count.set(0)    }    increment() {        const value = this.count.get() + 1        this.count.set(value)    }    *whatsUp() {        while (true) {            const count = yield* this.count            if (count > 10) {                throw new CounterMoreThan10Error()            }            yield (                <div>                    <div>Count: {count}</div>                    <button onClick={() => this.increment()}>increment</button>                </div>            )        }    }}const app = new App()render(app)

Пример на CodeSandbox


Мне банально непонятен весь этот звездочный код


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


  • yield* подключить поток и извлечь из него данные
  • yield отправить данные в поток
  • return отправить данные в поток и пересоздать генератор
  • throw отправить ошибку в поток и пересоздать генератор

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


Естественно этот вопрос нельзя обойти стороной, поэтому я добавил whatsup в проект js-framework-benchmark. Думаю кому-то он известен, но вкратце поясню суть этого проекта заключается в сравнении производительности фреймворков при решении различных задач, как то: создание тысячи строк, их замена, частичное обновление, выбор отдельной строки, обмен двух строк местами, удаление и прочее. По итогам тестирования собирается подробная таблица результатов. Ниже приведена выдержка из этой таблицы, в которой видно положение whatsup на фоне наиболее популярных библиотек и фреймворков таких, как inferno, preact, vue, react и angular



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


Прочие тактико-технические характеристики


Размер


Менее 3 kb gzip. Да это размер самого whatsup. Рендер добавит еще пару кило, что в сумме даст не более 5-ти.


Glitch free


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


Глубина связей


В комментариях к прошлой статье JustDont справедливо высказался по этому поводу:


Глубина связей данных не может превышать глубину стека вызовов. Да, для современных браузеров это не то, чтоб прямо очень страшно, поскольку счёт идёт минимум на десятки тысяч. Но, например, в хроме некоторой степени лежалости глубина стека вызовов всего лишь в районе 20К. Наивная попытка запилить на этом объемный граф может легко обрушиться в maximum call stack size exceeded.

Я поработал над этим моментом и теперь глубина стека не играет никакой роли. Для сравнения я реализовал один и тот же пример на mobx и whatsup (названия кликабельны). Суть примера заключается в следующем: создаётся "сеть", состоящая из нескольких слоёв. Каждый слой состоит из четырёх ячеек a, b, c, d. Значение каждой ячейки рассчитывается на основе значений ячеек предыдущего слоя по формуле a2 = b1, b2 = a1-c1, c2 = b1+d1, d2 = c1. После создания "сети" происходит вычисление значений ячеек последнего слоя. Затем значения ячеек первого слоя изменяются, что приводит к лавинообразному пересчету во всех ячейках "сети".


Так вот в Chrome 88.0.4324.104 (64-бит) mobx вывозит 1653 слоя, а дальше падает в Maximum call stack size exceeded. В своей практике я однажды столкнулся с этим в одном огромном приложении это был долгий и мучительный дебаг.


Whatsup осилит и 5, и 10 и даже 100 000 слоёв тут уже зависит от размера оперативной памяти компьютера ибо out of memory всё же наступит. Считаю, что такого запаса более чем достаточно. Поиграйтесь в примерах со значением layersCount.


Основу для данного теста я взял из репозитория реактивной библиотеки cellx (Riim спасибо).


О чем я ещё не рассказал


Делегирование


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


Асинхронные задачи


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


Роутинг


Вынесен в отдельный пакет @whatsup/route и пока что содержит в себе всего пару методов route и redirect. Для описания шаблона маршрута используются регулярные выражения, не знаю как вам, но в react-router третьей версии мне порой этого очень не хватало. Поддерживаются вложеные роуты, совпадения типа ([0-9]+) и их передача в виде потоков. Там действительно есть прикольные фишки, но рассказывать о них в рамках этой статьи мне кажется уже слишком.


CLI


Не так давно к разработке проекта подключился парень из Бразилии Andr Lins. Наличие интерфейса командной строки для быстрого старта whatsup-приложения целиком и полностью его заслуга.


npm i -g @whatsup/cli# thenwhatsup project

Попробовать


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


Примеры


Todos всем известный пример с TodoMVC


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


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


Sierpinski перфоманс тест, который команда реакта показывала презентуя файберы


Напоследок


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


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


Кроме того хочу выразить слова благодарности всем тем, кто меня поддерживал, писал в личку, на e-mail, в vk, telegram. Я не ожидал такой реакции после публикации первой статьи, это стало для меня приятной неожиданностью и дополнительным стимулом к развитию проекта. Спасибо!



С уважением, Денис Ч.


"Большая часть моих трудов это муки рождения новой научной дисциплины" Бенуа Мандельброт

Подробнее..

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

18.04.2021 16:05:03 | Автор: admin

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

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

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

Ну чтож, данная методика была предложена аж 1930-х годах советскими психологами. История подлинного авторства покрыта тайной, Биренбаум Г.В. в своей публикации приписывает авторство Лурии А.Р., сам же Лурия, причем гораздо позже (1964), отдал пальму первенства Л.С.Выготскому.

Методика достаточно проста в проведении. Этапы выполнения следующие:

  1. Исследуемому дается примерно следующая инструкция: Следующий тест будет на проверку Вашей памяти. Я буду называть слова или выражения, которые необходимо запомнить. Для того чтобы облегчить запоминание, на каждое слово нужно нарисовать рисунок, все равно какой, но так, чтобы он помог Вам вспомнить названное слово. Качество рисунка не имеет никакого значения, важно лишь, чтобы он помог Вам при запоминании. Слова и буквы не пишите. Также можно было бы обозначить, что рисунок должен быть именно "пиктограммой", то есть схематичным изображением, содержащим ключевые признаки понятия (на взгляд исследуемого). Иногда это нужно, что бы дифференцировать гиперпродуктивность в деятельности (в данном случае, в рисовании). Ведь если когда исследуемый, который "понял" инструкцию, приступая к заданию начинает рисовать "джоконду в гроте" на 30мин, есть повод задуматься о том, все ли хорошо с критичностью мышления. Набор стимулов обычно такой: веселый праздник, тяжелая работа, вкусный ужин, болезнь, печаль, счастье, любовь, развитие, разлука, обман, победа, подвиг, вражда, справедливость, сомнение, дружба.

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

Среди однозначных достоинств данной методики можно отметить:

  • то, что методика, представляет для исследователя широкий диапазон данных, среди которых:

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

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

    3) Динамические характеристики мышления под "когнитивной нагрузкой" (то каким образом видоизменяются характеристики мышления с точки зрения временных характеристик, это тоже важно)

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

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

Среди критичных недостатков данной методики, на мой взгляд, можно отметить:

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

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

    2) "Стандартизированный (почти)", разработанный Б.Г.Херсонским, который пред-ставляет собой сложную, комплексную и трудоемкую оценку каждого отдельного образа и всех образов в целом по множеству параметров (графическим, грамматическим, графическим, содержательным, частотным, индивидуально-значимым, а также по той самой "адекватности", черт ее дери). Предполагается, что сравнивая данные количественные и качественные характеристики и сопоставляя их с данными "нормативного" выполнения, можно делать какие-то заключительные выводы, которые будут отвечать изначальным общим целям патопсихологического обследования. Ну, если честно, то как то связи не вижу здесь никакой. Особенно, с учетом того, что автор сам обозначает мысль а огромной вариантивности ответов психически здоровых людей.

Резюмируя вышесказанное, хотелось бы обозначить актуальное представление большинства думающих и практически-ориентированных специалистов что все таки с этим делать. Однозначно, есть ряд принципов, обозначающих, в некоторой степени "нормативное" выполнение этой методики. Цитируя того же Б.Г.Херсонского:

  1. Здоровые исследуемые способны подобрать образы на все понятия, представленные в стандартном наборе стимулов.

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

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

  4. У здоровых исследуемых минимальное количество "шоковых реакций", "отказов".

  5. Большую часть образов здоровых исследуемых можно обозначить как "атрибутивные" и "конкретные", количество индивидуально-значимых и латентных образов минимально.

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

Спасибо за внимание.

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

11
Подробнее..

Гений и не лечишься. Является ли одаренность психическим расстройством?

16.05.2021 14:08:59 | Автор: admin


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

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

Идеи о том, что гениальность это психическая болезнь, существовали даже в античные времена: еще Аристотель писал, что ни один великий ум не существовал без примеси безумия. Одним из первых ученых, всерьез занимавшихся исследованием гениальности, был итальянский судебный психиатр Чезаре Ломброзо, который опубликовал в 1863 году фундаментальный труд с говорящим названием Гениальность и помешательство. В своей книге Ломброзо рассматривал биографии многих талантливых людей своего времени, и практически для каждого из них подобрал подходящий психиатрический диагноз. Досталось от итальянца знаменитым ученым, музыкантам и писателям. Благо, все персонажи его бестселлера к моменту выхода книги уже умерли, поэтому автору удалось избежать судебных исков о защите чести и мужского достоинства.



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

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



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

Наиболее распространенное среди представителей креативных профессий явление это депрессия в ее клиническом определении. За ней следуют такие расстройства, как алкоголизм, наркомания, биполярные аффективные расстройства (маниакально-депрессивные психозы), заболевания шизофренического спектра и различные суицидальные проявления. При этом для разных сфер творческой деятельности показатели тоже разнятся. Авторы исследования утверждают, что, например, почти 87% знаменитых поэтов страдали от той или иной формы психопатологии, а среди выдающихся ученых этот показатель достигает лишь 28%, что близко к средним показателям в популяции. Более того, в семьях, подаривших миру сразу нескольких талантливых людей, психические расстройства встречаются чаще, чем в семьях, обделенных талантами. Проведенные экспертами психометрические исследования демонстрируют, что очень многие одаренные люди могут проявлять те же симптомы, что и пациенты с психиатрическими патологиями, но у первых они обычно слабее и мягче выражены. Кроме того, некоторые гении научились использовать эти проявления в своих интересах как один из творческих инструментов.

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



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

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

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

В непосредственной связи между талантом и психопатологиями есть все же некоторые сомнения, о чем говорит в своей статье BBC Future. Хотя частично выводы автора этой публикации совпадают с уже озвученными выше доводами индийских психологов: Используя данные официальной переписи населения Швеции, исследователи установили, что среди представителей подобных творческих профессий в 1,35 раза чаще встречаются люди, страдающие биполярным расстройством (которое ранее называлось маниакально-депрессивным психозом), однако симптомы тревожности, депрессии или шизофрении наблюдаются у них в той же мере, что и у специалистов из других сфер. Аргументом в пользу наличия подобной связи являются исследования американского психолога Кей Редфилд Джемисон, против публикации английского врача Хэвлока Эллиса, который никакой корреляции, наоборот, не обнаружил.

Однако велик список талантов, чьи психологические отклонения или серьезные психиатрические диагнозы были подтверждены документально. Это, в частности, Николай Васильевич Гоголь, Эрнест Хемингуэй, Эдгар Аллан По, Микеланджело, Винсент Ван Гог, Роберт Шуман, Моцарт, Бетховен, Джон Нэш, Вуди Аллен и многие, многие другие. Но гораздо больше тех, кто балансирует в пограничном состоянии, то есть, проявляет очевидные способности в какой-то творческой сфере, однако пока еще не окончательно поехал кукухой. Помимо представителей именно творческих профессий писателей, художников, поэтов или актеров, широко известны случаи ментальных отклонений у талантливых людей, проявивших себя в совершенно других областях человеческой деятельности.



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

Если же мы посмотрим на список знаменитостей, страдавших биполярным расстройством личности, то увидим, что его преимущественно составляют композиторы, художники, писатели, артисты, реже спортсмены, политики и общественные деятели. Встречаются среди них и довольно неожиданные персоны, такие как, например, Вивиан Ли, актриса, сыгравшая Скарлетт в классической экранизации Унесенных ветром, известный музыкант Френк Синатра, Кэтрин Зета-Джонс, Селена Гомес, знаменитый режиссер Френсис Форд Коппола, а также человек-шпагат Жан-Клод Ван Дамм.

Помимо прочего Ван Дамм страдал от пагубного пристрастия к кокаину, к которому приобщился, по его собственным словам, из-за крайне напряженного графика съемок. Актер утверждал, что тратил на это вещество порядка 10 000 долларов в неделю и потреблял до 10 граммов в день. В результате в 1999 году он был арестован за вождение в нетрезвом виде, после чего проходил длительный курс реабилитации от наркозависимости. Диагноз биполярное аффективное расстройство артисту поставили в 1998 году, тогда же ему была назначена постоянная медикаментозная терапия. В реалити-шоу Behind Closed Doors в 2001 году Ван Дамм говорил о том, что перепадами настроения он страдает давно, но с возрастом это превратилось в серьезную проблему: Когда я был молод, у меня было такое колеблющееся настроение. Но что я могу сделать? У меня сильное биполярное расстройство, и я принимаю лекарства от этого....

Еще одним известным деятелем кино с биполярным аффективным расстройством и циклотимией является известный британский комедийный актер и режиссер Стивен Фрай. О своем заболевании Фрай даже снял документальный фильм Секретная жизнь манимакально-депрессивного пациента (The Secret Life of the Manic Depressive), удостоенный премии Эмми и номинированный на British Academy Television Awards в 2007 году. В фильме Фрай взял интервью у других известных актеров с таким же диагнозом: Робби Уильямса, Кэрри Фишер, Ричарда Дрейфуса и Тони Слэттери.



Заболевание заметно мешало Стивену Фраю на протяжении всей его карьеры: резкие перепады настроения и неожиданные приступы депрессии часто приводили к тому, что он бросал все дела и убегал со съемочной площадки или театральной сцены. Наиболее ярким эпизодом является подобный случай в 1995 году во время подготовки к премьере спектакля West End Cell Mates, когда Фрай покинул театр, сел на паром, идущий из Англии в Европу, и фактически пропал без вести, объявившись лишь через пару дней в Бельгии. Фрай несколько раз пытался покончить жизнь самоубийством, в последний раз это случилось в 2012 году. Он рассказал в интервью Ричарду Херрингу, как это произошло: во время очередных заграничных съемок в результате нервного срыва артист принял огромное количество таблеток и огромное количество водки, после чего его пришлось вернуть в Великобританию, чтобы он находился под присмотром врачей. Только регулярный прием назначенных медиками препаратов помог Фраю, по его собственным словам, стабилизировать состояние и ослабить проявления недуга.

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

Проведенное А.М. Людвигом исследование 1000 выдающихся людей, чьи биографии были опубликованы в New York Times Book Review с 1960 по 1990 год, показало высокий уровень злоупотребления алкоголем среди художников и особенно писателей. Эрнеста Хемингуэя можно назвать хорошим примером гениального автора, которого алкоголизм сначала привел к Нобелевской премии по литературе, а потом к преждевременной смерти. Чарльз Диккенс страдал от пристрастия к опиуму, которое также сыграло трагическую роль в его судьбе. Сергей Есенин, Владимир Высоцкий, Френсис Скотт Фицджеральд, О.Генри, Эдгар Аллан По, Эрих Мария Ремарк, Сергей Довлатов эти имена у всех на слуху, и все эти талантливые люди страдали алкоголизмом.

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



VDS серверы от Маклауд просто сумасшедше быстрые.

Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!

Подробнее..

Заметки из больницы

29.09.2020 10:08:21 | Автор: admin
Эту статью я начал писать, находясь в стационаре Рижского психиатрическо-наркологического центра и подлечивая депрессивный эпизод. Загнал себя чуток чередой стрессов и затянувшимся выгоранием. Будучи в таком интересном и щекотливом месте, я решил пообщаться со специалистами и узнать их мнение о нас, программистах, и родственных профессиях, о свойственных нам проблемах и о том, что нужно делать вовремя, чтобы не проследовать по моим стопам. В общем, по-своему протягиваю хабровчанам руку помощи.



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

Что говорит психолог?


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



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

Тревожность в целом характерна программистам?
Да. Иногда, конечно, она зависит от характера работы. Программисты есть программисты, но обстоятельства работы очень отличаются. Некоторых проверяют, сколько сидишь.

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

Вам кажется, скорее особенности типа личности помогают стать программистом, или работа программистом приводит к подобным особенностям?
Я думаю, и того, и другого понемножку. Что я могу сказать хорошего: сколько я работаю с программистами, довольно удобно работать. Очень быстро выстраивается понимание благодаря высокому уровню когнитивного развития, мышления. Эмоциональная регуляция меньше, может быть. Мне кажется, есть характерный тип личности: лучше развито понимание, логическое мышление, а вот эмоциональная сторона чуть слабее. С другой стороны это же работа абстрактная, в реальности её нету. И её выбирают люди, которым легче концентрироваться на абстракциях, а не только на конкретных вещах. И, конечно, вопрос в том, как потом компенсировать то, что мы сидим в виртуальном мире.

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

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



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

Помимо отношений и тревожности, какие ещё проблемы возникают? Что на третьем месте? Те же депресии часто встречаются?
Скажу откровенно, у меня с депрессией, пожалуй, и не было человека, во всяком случае из программистов.

Значит, я первый.
(Смеётся) Да, особенно не было. Было про смену работы. Программисты могут работать в разных условиях, разная организация рабочих команд. Где-то команда разбросана по разным странам, у кого-то раз в неделю созвон, и им хватает, а кому-то нужен офис. И с некоторыми мы разбирали организацию труда в этом аспекте. Но основное это всё же отношения и тревожность.

Понял, спасибо за небольшое интервью.



Для тех, кто поленился прочитать про шизоидный тип, рекомендую не полениться. Ну и сразу отмечу, что это не про шизофрению. Если вкратце, ему характерны замкнутость в себе, кажущаяся самодостаточность, часто незаурядные способности, а поверх сложности в построении отношений. Всё то, о чём и рассказала психолог. Таких людей 1-2%, и это не расстройство, это просто набор граней нашей личности, с которыми как-то можно и нужно жить. Кстати, проголосуйте в опросе, узнали Вы себя в описании или нет. Посмотрим, отличается ли сообщество хабра в процентном соотношении.

А что расскажет психиатр?


С директором центра Велдре, где я находился на лечении, профессором Рижского университета Страдыня, мы проговорили примерно полчаса. И, я бы сказал, этот диалог затронул схожие проблемы, но на более глубоком уровне.



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

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

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

То есть, в основном это либо шизофренический спектр, либо депрессивный.
Депрессивно-невротический, на почве больших перегрузок, несоблюдения режима еды, режима дня, режима отдыха Программист остаётся программистом 24 часа, и это может довести до срывов. И, конечно, к ним нужен отдельный подход. У меня есть пациенты, которые хорошо работают, даже с тяжёлыми заболеваниями. Они чувствуют, что они нужны на рынке труда, и работодатель относится к ним лояльно: разрешает прийти попозже, поработать вечером, адаптирует нагрузку. Если работодатель приспосабливается получает максимум от этого человека. А если начинать надавливать, давать большие нагрузки, неправильно планировать, тогда могут быть срывы.



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

Плюс, конечно, в обоих вариантах важно соблюдать режим, насколько возможно. И попытаться отключаться в течение дня. Поработал 2 часа хотя бы на 10-15 минут выйти из офиса, посмотреть вдаль, размять глаза, отдохнуть, подышать свежим воздухом. Не стоит работать по 6-8 часов без перерыва и забывать даже покушать. Ну или стандартное кефир, батон, пачка чипсов Еда тоже очень важна. Идеально хотя бы день-два на выходных, например, отключаться и обходиться без компьютера. Конечно, свежий воздух, прогулки. Хоть минимальная физическая активность. Даже если спортсменом и не станет, но хоть быстрым шагом пройтись, шаги посчитать телефоном или браслетом. И еда, конечно. Найти этот момент, остановиться, покушать. И даже при работе из дома важно стараться сохранить этот режим. Какие бы там трудности в работе не возникали, эти элементарные вещи очень важно сохранить.

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

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

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

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

Например, меньше работать.
Тут, конечно, кажется в тот момент, что и мне надо, и всем надо

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



Понял. А по поводу невротическо-депрессивного спектра?
Где-то похоже, но, конечно, в этих случаях чаще бывают внешние факторы, которые провоцируют: ситуации в семье, какие-то конфликты с работодателем или сотрудниками. Эти ситуации в большей мере могут повлиять. Тоже появляется риск веществ или алкоголя. Может возникать тревога, из-за которой немного вечером начинают выпивать. И возникают негативные шаблоны реакции. Но тут факторы внешние, которые надо сугубо подлавливать такие ситуации и анализировать, стоит ли там и так работать. Может, стоит обсудить ситуацию, что там неправильно. Иногда бывает неправильная организация труда на работе. Например, если человек хорошо работает и может много сделать, всё на него валят. Он не может сказать нет, на него валят, он соглашается, а ещё десять человек просто сидят.

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

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

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

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

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

Тут даже вопрос не в наезде со стороны, а в том, что я как программист не то что ожидаю, что мне кто-то сообщит об ошибке, я просто понимаю, что я что-то сделал, и оно с первого раза не заработало. И я ещё должен потратить несколько итераций на то, чтобы то, что я сделал, заработало. То есть у меня к собственному труду есть постоянное отрицательное ожидание. Это может влиять, или просто люди вырабатывают стрессоустойчивость?
Должна вырабатываться. Это зависит от типа личности. Каждый программист индивидуален. Есть люди невротического склада. Они с детства обо всём волнуются, всё хотят сделать идеально. Таким будет труднее. Он хочет всё сразу, он хочет, чтобы заказчик сказал: Хорошо получилось, нормально. Ну, что-то не доглядели, да. Ему такое отношение нужно, он всё равно волнуется. Есть люди с хорошей самооценкой, они понимают свой уровень. Совет профессионально подходить. Вы понимаете, что ни один серьёзный скрипт не пошёл с первого раза. Когда вы учились, вам это сказали, наверное. Это профессионализм. И вы, конечно, хотите меньше ошибок. Вы посмотрели архитектуру, которая тоже может быть сделана тяп-ляп, вы понимаете, где что может пойти не так, где будет много вопросов и так далее.

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

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

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

У нас просто одна из особенностей нам нужно очень много параметров того, что мы делаем, держать в голове. Поэтому нам не хочется прерываться: если мы прервёмся, этот карточный домик тут же падает. И нам его каждый раз после перерыва надо выстраивать.
Ну это как мне один рассказывал про дизельные локомотивы. Локомотив если работает, всё отлично. Когда ресурс снижается до каких-то 50%, тогда нужно делать капитальный ремонт, и он прослужит намного дольше. А в реальной жизни если он работает, кто ему будет этот ремонт делать? Мы думаем про текущий момент, а про то, как наш ресурс может дольше продержаться об этом мы забываем. Кто же будет исправный локомотив на капитальный ремонт давать, даже если он будет работать в 2-3 раза дольше? Так и в жизни. Мозг держится, но в какой-то момент может не выдержать.

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

Не пить тогда, когда какая-то тревога, когда хочется что-то этим алкоголем решить. Тогда начинается ежедневное употребление по 100 грамм, чтобы успокоиться. И возникает серьёзная проблема, подкрадывается алкоголизм. Или второй вариант, когда тусовка, и мы напиваемся до белых мишек. Когда хорошая компания, когда хорошее самочувствие, тогда не так много и надо, и за бокалом вина или кружкой пива под хороший разговор можно просидеть весь вечер. Редко кто совсем не пьёт. Но проблема начинается, когда мы начинаем решать свои проблемы, например, в отношениях, или усталость алкоголем, или тревогу. Алкоголь сбивает рецепторы, и потом очень трудно лечить. Особенно женщинам нужно быть осторожными. Там проблема серьёзнее. Мужчины хоть как-то признают эту проблему и решают. Женщины не признают, не решают. Уже каждый вечер бутылка вина, чтобы отключиться это очень серьёзно.

Где грань находится между как-то многовато и уже алкоголизмом?
Алкоголизм начинается тогда, когда алкоголь начинает доминировать в жизни. Например, у меня есть выбор: провести день с семьёй и детьми или встретиться с друзьями и выпить, и я чувствую, что выбор идёт в сторону алкоголя. Если мои воспоминания и хорошие жизненные моменты связаны с тем, когда выпили, и как там было, это уже значит, что в мозгу доминирует алкоголь. Это уже так называемый бытовой алкоголизм, пред-стадия алкоголизма. Был с друзьями и что-то забыл купить или сделать. Или выпил вечером и утром пришёл с похмельем на работу, не смог нормально работать, день прошёл так себе. Вроде с работы и не выгнали, как-то справился. Это значит, что я уже не так критично отношусь, и алкоголь уже важен в моей жизни. Это уже признак. К сожалению, в обществе 60-80% людей бытовые алкоголики. К сожалению, мы сами не замечаем, что это так.

То есть, в целом, среди взрослого населения можно сказать, что больше половины?
Да, да, больше половины точно. Даже не подозревают: Это же ерунда, ну так, выпиваем. В Англии, например, там же все сделки идут только через пабы. Там офисы полдня сидят в пабах. Там уже пиво, какие-то разговоры, вся жизнь фактически идёт через алкоголь. Я бы не сказал, что это хорошо для здоровья людей. Много людей болеют, и система здравоохранения там хоть и хорошая, но уже не справляется.

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



Ну что сказать? Ни добавить, ни убавить. Делаем выводы, каждый для себя.

А что с нашим телом?


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

  • Застойные явления в венозном бассейне тромбозы глубоких вен, тромбофлебиты, пост-тромбофилический синдром, геморрой. При постоянном нарушении венозного оттока из-за неудобной позы в определённом месте возникает турбулентный поток. И если в том же месте есть воспаление сосудистой стенки и нарушение реологических свойств крови (вязкость и пр.), в этом месте есть отличные условия для образования тромба.

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

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

    И третья проблема из этой сферы геморрой. Тут сидячий образ жизни основной фактор риска. Часто это ещё может быть связано с проблемами с печенью, т.к. это всё один венозный бассейн система воротной вены. Тут симтомы понятны, я думаю: боль в области анального отверстия, геморроидальные узлы, которые можно увидеть и пропальпировать, если это внешний геморрой. Внутренний, впрочем, тоже можно пропальпировать. Что делать с геморроем? Удалять. Мази, свечки это всё хорошо, но Это по сути то же расширение вены, только чуть выше. И с растянутую венозную стенку никакими мазями не стянешь. Это как резинка на штанах. Если умеренно её растягивать, она вернётся в предыдущее состояние. Но если её сильно растянуть, она такой и останется.
  • Кератоконьюктивит проявляется сухостью в глазах, покраснением, ощущением песка в глазах, раздражением, слезоточивостью. Чем больше трёшь, тем хуже становится. Проблему связывают с длительной работой с экраном. Просто когда человек долго смотрит в экран, он мало моргает. Именно с этим и связан кератоконьюктивит у айтишников. Как этому помочь? Кроме как меньше смотреть в экран, никак. Но сложно себе это представить. Лечить его очень весело, нужно закапывать каждые 3 часа глаза всякими каплями на основе антибиотиков. Плюс искусственная слеза, которой пользуются те, кто носит контактные линзы. Ею время от времени можно смачивать глаза.
  • Корешковые синдромы. Всё, что любит делать наш хребет плавать и лежать на валике. Любая другая активность для хребта вредна. И больше всего вредно сидение. Хождение, стояние не так вредно. Сидение тут, пожалуй, конкурирует с неправильным подъёмом тяжестей. Всё это сводится к вертикальной компрессии хребта. От сидения возникают нарушения в межхребетных дисках, так называемые протрузии. Раньше это называли остеохондрозом, но сейчас модные врачи не любят этот диагноз. Остеохондроз нам достался как бесплатный придаток к прямохождению. Вертикальная компрессия хребта у нас возникает постоянно при хождении, сидении, стоянии, подъёме тяжестей.

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

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

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

    Что можно сделать с проблемой, подаренной нам природой вместе с прямохождением? Ну я не знаю, честно говоря. Но если речь идёт о работе, стоит чаще изменять позицию. В крутых зарубежных офисах устанавливают столы, позволяющие изменять высоту, чтобы можно было поработать сидя 40 минут, поработать стоя 40 минут, поработать лёжа 40 минут. И так весь рабочий день. Собственно, это уже правило хорошего тона для работодателей по отношению к сотрудникам устанавливать такие столы. А так почаще менять позицию, почаще разминаться. Скажем, завести правило себе каждый час вставать на 5 минут и делать разминку. Правда, от уже существующего остеохондроза это уже не спасёт.

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

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

И в заключение


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

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

Немного рекламы


Спасибо, что остаётесь с нами. Вам нравятся наши статьи? Хотите видеть больше интересных материалов? Поддержите нас, оформив заказ или порекомендовав знакомым, облачные VPS для разработчиков от $4.99, уникальный аналог entry-level серверов, который был придуман нами для Вас: Вся правда о VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps от $19 или как правильно делить сервер? (доступны варианты с RAID1 и RAID10, до 24 ядер и до 40GB DDR4).

Dell R730xd в 2 раза дешевле в дата-центре Equinix Tier IV в Амстердаме? Только у нас 2 х Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 ТВ от $199 в Нидерландах! Dell R420 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB от $99! Читайте о том Как построить инфраструктуру корп. класса c применением серверов Dell R730xd Е5-2650 v4 стоимостью 9000 евро за копейки?
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru