Не понимаете, как работают TCP или GraphQL? Нестрашно: объяснили работу сложных технологий так, что поймёт даже ребёнок.
Часто разбираясь в новой для себя теме, мы ищем более простое объяснение разных вещей. В этой статье мы объяснили работу TCP, GraphQL, Bitcoin, контейнеров, WebSockets, MapReduce, монадов так, что это доступно даже пятилетнему ребёнку. Приступайте!
TCP
Вы с другом должны уметь делиться игрушкой. Если выбираете для общения TCP
- Вы спрашиваете друга, можете ли поиграть с его игрушкой;
- Ваш друг спрашивает вас, действительно ли вы попросили его игрушку;
- Скажите своему другу, что вы попросили эту игрушку;
- Он дает вам игрушку.
UDP: Ваш друг бросает на вас игрушку и уходит.
GraphQL
В школе наступил обеденный перерыв, и в столовой сегодня подают твои любимые котлетки с пюрешкой.
Ты был бы счастлив питаться только этим, но как прилежный ребёнок, ты должен взять ещё тушёную капусту, огурцов и, конечно, попросить подливку.
Разумеется, ты не хочешь, чтобы вся твоя тарелка была в капусте и подливе. Поэтому, ты даёшь тарелку повару и тебе приходится объяснять, что ты хочешь пюре, котлетку побольше, одну ложку капусты, подливку налить с краю, огурцов положить на другой край. Но в столовой изъясняться совсем не удобно. Поэтому, ты используешь это:
Это GraphQL-тарелка. В ней легче обозначить, сколько чего нужно положить. Повар берёт у тебя эту тарелку, а кладёт мясо с подноса Mongo, капусту и пюре из кастрюлек Postgres. Какая-то еда находится на кухне, наверняка в другой посуде — да где угодно, для тебя это не важно.
В некоторых столовых (типа «REST») можно пользоваться только стандартными тарелками и нужно подходить за каждым блюдом отдельно.
Таких столовых много, работают они по простой схеме. Но «SOAP» столовые, в которых можно использовать GraphQL-тарелки, подходят для школьников больше — не нужно много раз стоять в очереди и просить у повара по одному новому блюду.
Bitcoin
Представьте, что вы хотите купить игрушечный грузовик вашей сестры. Родители дают карманные деньги, но не наличными — они сообщают, сколько денег выделили и вы запрашиваете наличные деньги с баланса, когда вам это нужно. Вы хотите потратить 5 долларов ваших карманных на покупку игрушечного грузовика, но сестра просто добавит деньги к своим карманным, никаких живых денег. Вы решили записать, что перевели сестре 5 долларов на бумажке.
Каждый из вас будет подписывать бумажку с вашим именем, но вы хотите, чтобы эта покупка была секретной, чтобы ваши друзья не знали, что вы владеете игрушечным грузовиком. Вы с сестрой по очереди записываете незнакомые друг другу слова, чтобы никто не смог ничего подделать. Вы берете этот документ и копируете его один раз. Таким образом, у вас есть запись о покупке. В следующий раз, когда она захочет потратить свои деньги, она может использовать запись транзакции, чтобы получить 5 долларов.
Остается решить одну проблему: соперничество между вами и сестрой. Вы не хотите, чтобы сестра утверждала, что грузовик все еще принадлежит ей. И она не хочет, чтобы вы заявляли о продаже грузовика. Итак, вы берете свою копию записи транзакции, делаете две копии и кладете на стол для родителей.
У каждого из ваших родителей есть место, где они хранят записи транзакций. Они добавляют новые записи, проверяя друг друга, чтобы убедиться, что записи идентичны и лежат в одном и том же порядке.
Когда твоя сестра хочет потратить 5 долларов, которые она заработала, все, что ей нужно сделать, это написать те самые непонятные слова, которыми она подписалась на листе бумаги, положить в запечатанный конверт и положить в комнату родителей.
Но погодите! Как родителям понять, чьи это карманные деньги, чтобы не потратить лишнего? Предположим, деньги адресуются не по настоящему имени, а по прозвищам, которые родители могут даже не знать. А записи о передаче денег всегда сопровождаются длинными словами, прозвищами участников сделки и подписями.
Объяснение
Благодаря этой системе ваши родители могли бы иметь тысячи детей, каждый со своими карманными деньгами, и вести идеальный учет того, каков баланс каждого ребенка, даже если они не знают, чей счёт есть чей. Дети могут совершать операции деньгами и обратно все время, и они не потеряются. Но к этому моменту рабочая нагрузка на управление всеми этими транзакциями довольно велика, поэтому родители приглашают своих друзей жить у вас дома и помогать им. Ваши родители откладывают часть денег, которые зарабатывают, и отдают их друг другу и друзьям, исходя из того, сколько транзакций они проверяют каждый день. И копировальная машина работает все время, потому что каждый должен иметь коробку, в которой есть все транзакции, все в одном и том же порядке.
В биткоине ваш компьютер — это коробка. У вас есть копия буквально каждой транзакции Bitcoin, которая когда-либо случалась, как и у любого другого пользователя Bitcoin (нет родителей или, другими словами, нет центрального органа). Когда вы хотите совершить сделку, вы делаете это анонимно, но вы и другой участник транзакции используют математику для генерации открытого ключа (вроде непонятных слов), что доказывает, что деньги принадлежат компьютеру, отправляющему ключ, а после, они становятся собственностью компьютера-получателя. И каждый, кто выполняет вычисления, необходимые для проверки транзакций, получает за это небольшое количество биткоинов.
Контейнеры
Наверняка у тебя есть игрушки, которые нужно собирать из деталек. Например, для того, чтобы собрать дом, понадобятся детальки lego, а для поезда нам пригодились бы вагоны, крепления и, конечно же, рельсы, не по ковру же мы будем его возить. Обрати внимание, что для разных игрушек часто требуются разные виды деталек.
Контейнер — это коробочка, в которую ты складываешь все детали, необходимые для полной сборки игрушки. Так и каждое приложение(игрушка) в мире программирования имеет прямые или косвенные зависимости, без которых оно не сможет функционировать.
Часто случается, что программа работает у разработчиков как нужно, но на машинах заказчика с ней случается что-то странное — она работает медленно, выдает ошибки или вообще отказывается запускаться. Часто причина заключается в том, что окружение заказчика не содержит всех необходимых программе «деталек». Собранный тобой поезд не поедет у друга, если ты не одолжишь ему еще и рельсы. Тут контейнеры и пригождаются: мы собираем в «коробочку» все «детальки», чтобы заказчик смог играть, не заботясь о том, хватает ли у него деталек для твоей игрушки.
Также можно хранить несколько контейнеров с деталями, чтобы составлять большие и классные игрушки из маленьких.
Виртуальная машина — это тоже коробочка с детальками, но каждый раз, как ты захочешь собрать игрушку и поиграть с ней, тебе придется поесть не очень вкусных овощей.
WebSockets
У вас есть соглашение с вашим лучшим другом, что он поможет с математикой.
Когда у вас возникнет вопрос, позвоните ему, подождите, пока он ответит, затем задайте свой вопрос и послушайте ответ. Затем он повесит трубку, и вы продолжите свою домашнюю работу.
В большинстве вечеров вы звоните ему несколько раз в течение часа или около того. Иногда он слишком занят, чтобы отвечать, поэтому вы вешаете трубку и пытаетесь дозвониться через несколько минут.
Но иногда домашняя работа слишком сложная, и вы фактически звоните ему каждые пять минут. Хотя он не против помочь вам, вас обоих не устраивает процесс набора номера, ожидания ответа на вопрос и сбрасывания трубки, при том, что это повторится всего через несколько минут.
Наконец, вы соглашаетесь на разумное решение. Вы набираете его и держите линию открытой. Когда ты работаешь самостоятельно, наступает тишина, но когда у тебя есть вопрос, тебе просто нужно начать говорить, и он уже слышит тебя. Когда ваша домашняя работа закончится, вы можете повесить трубку.
Ваш друг — это сервер, вы — приложение для браузера, вызов — это сетевое подключение, а удержание соединения — это соединение с помощью WebSocket.
MapReduce
Итак, тебе 5 лет. Ты хочешь посчитать, сколько у тебя дома деталей Lego. Они все хранятся в пяти коробках, и ты просишь четырёх своих друзей помочь — даёшь каждому по коробке.
Через несколько дней подсчётов, не без помощи родителей, они снова приходят к тебе с коробкой и листочком, на котором написано число (хорошо, что они всё-таки вернули конструктор):
- Аня насчитала 120 деталей
- Белла — 65
- Ваня — 99
- Гера — 87
- Денис — 77
Ты просишь родителей сложить эти числа (потому что сам пока не умеешь), и они говорят тебе, что всего получилось 448 деталей. Так вот: Map: «друзья, посчитайте детали в коробках» Reduce: «посчитать сумму чисел».
Или ещё один пример:
Монады
Это как раз та самая вещь, о которой в первый раз стоит узнать на пальцах!
В свои пять лет ты (интересующийся монадами) уже знаком с integer, string, boolean, можешь делать с ними некоторые операции, написать приведение строки к числу и т. д. Такие данные — простые.
Увы, в реальности информация устроена сложнее. Часто бывают загвоздки:
- мы можем пытаться считать то, что возможно существует, а может и нет!
- значений может быть много;
- чтобы получить данные, нужны I/O операции;
- значение может существовать… когда-то в будущем;
- оно может содержать ошибки;
- значение может зависеть от изменений во внешнем мире;
- и т. д.
Это, конечно, не законченный список, но принцип становится понятен. И как же выполнять вычисления в таком хаосе? На помощь разработчику приходят хитрые абстракции.
Да, пришло время для монад!
Монада работает как контейнер, позволяющий нам работать с содержимым, не задумываясь над проблемами выше. Как они решаются монадами?
- если значение возможно существует, оно управляется монадой Maybe;
- когда значений может существовать множество, используется монада List;
- если требуются операции ввода-вывода, используется монада IO;
- для значений, которые появятся когда-то в будущем, существует монада Promise/Future (та самая Promise из JavaScript? Да, это что-то вроде монады);
- когда значение может вызывать ошибки, оно управляется монадами Error/Result/Either;
- если оно зависит от изменений состояния внешнего мира, используется монада State.
Впечатляет, правда? Вы можете спросить: «если это просто контейнеры, что же в них особенного?».
Действительно, помимо того, что это контейнеры, для них определены операции.
- return: как «положить» обычное значение в контейнер-монаду? Просто сделать return!
- fmap: у вас есть функция, которая принимает String, а возвращает Int. Возможно ли как аргумент подать Maybe String, чтобы получить Maybe Int? Да, конечно, можно — просто сделать fmap!
- join: так, а если значение лежит в контейнере внутри другого контейнера? Для этого есть функция join: из Maybe (Maybe String) ею можно сделать Maybe String.
- bind или chain или >>= : для сокращения комбинации fmap + join, которая встречается довольно часто (flatMap).
- liftM, liftM2, liftM3..: если у нас есть функция, к примеру, принимающая String, возвращающая Int, то можем ли мы сделать функцию, принимающую Future String, возвращающую Future Int? Да, мы просто «поднимаем» её в мире монад!
- >=> (ага, ещё один странный символ — композиция монад): вот например есть две функции. Одна (String) → IO Int, а другая (Int) → IO Boolean. Можно ли их объединить в одну (String) → IO Boolean? Да, конечно, мы просто соединяем их с >=>!
Вот и всё, что нужно знать о монадах в пять лет!
Это объяснение написано со многими упущениями и не включает в себя рассказ о функторах. Подрастёте — изучите.
Материалы, которые могут вас заинтересовать:
Источник: dev.to
Комментарии