Ещё лет 5 назад на собеседованиях с backend-разработчиками был популярен вопрос: как переименовать колонку в высоконагруженной таблице (возможны вариации: как сделать любой другой alter table)? Ответ мог быть примерно следующий:
Зачем такие сложности с создаем новой колонки и постепенной миграцией? Почему бы просто не задать всем колонкам уникальное имя которое никогда не захочется поменять (случайный айдишник) а уже в коде хранить соответствие имя -> id при работе с этой бд. Тогда переименование колонки сведется к простейшей операции замены одного имени на другое в коде вообще без каких-либо затрат со стороны бд
вы только представляете а кто-то уже так делает и зарабатывает миллионы — вот один комментарий на HN который недавно набрал популярность в твиттере https://news.ycombinator.com/item?id=27454589
I currently have 10 fully remote engineering jobs. The bar is so low, oversight is non-existent, and everyone is so forgiving for under performance I can coast about 4-8 weeks before a given job fires me. Currently on a $1.5M run-rate for comp this year. And the interviewing process is so much faster today, companies are desperate, it takes me 2-3hrs of total effort to land a new job with thousands to chose from.
Насчет ангуляра не скажу но с реактом я применяю другой подход — просто пишу функции инлайном и таким образом вообще избавляюсь от диллемы именования функций и заодно очень просто и круто решается вопрос сематического соответствия кнопки и обработчика — вот есть кнопка а значит обработчик функции будет на этой кнопке (или наоборот — если видишь обработчик кнопки то и кнопка будет рядом)
Тут можно сказать мол "да ты захламляешь шаблон как такое вообще читать и поддерживать когда мол верстка в перемешку с логикой?" на что я отвечу "а code folding (сворачивание) в редакторе кода для кого придумали?" Если хотите видеть/редактировать только верстку то можно легко свернуть весь код обработчиков и увидеть чистый шаблон. И наоборот — если хотите посмотреть что делает какая-то кнопка то перемещаем мышку влево на пару сантиметров и кликаем-раскрываем обработчик кнопки.
Это намного удобнее чем переходить в отдельный файл или скроллить экран вверх-вниз (когда выносим обработчик функции в другое место). Это также удобно в поддержке — если допустим у нас поменялся дизайн/ux/логика и поменялась верстка в результате которой нужно удалить какой-то блок вместе с кнопкой то я удаляю нужный кусок верстки и вместе с этим удалится и обработчик этой кнопки поскольку он записан инлайном — мне не нужно беспокоится а не удалил/почистил ли я различные обработчики в другом файле или других местах по коду
И то же самое с добавлением какой-то фичи — я пишу кнопку и тут же пишу обработчик этой кнопки рядом и мне не нужно думать над тем куда вынести этот обработчик а главное — какое имя придумать этому обработчику. И также это удобно при ревью кода — когда добавляется какая-то фича то в git diff видишь изменения только в одном месте а не размазаны по кусочкам на кучу файлов/мест (верстка в одном месте, обработчик в другом месте и т.д)
Как вебсокеты могут быть более тяжёлой штукой чем http-запросы? Вы понимаете как работает http? HTTP-запрос это точно такое же тсп-соединение как и вебсокеты и ничем не легче по "тяжести". И если интернет-соединение нестабильное то http-запрос будет точно также обрываться с ошибкой как и вебсокет-соединение (и соотвественно нужно делать повторный запрос/установку соединения), в этом плане я вообще не вижу никакой разницы.
А вот во многих моментах http намного хуже и имеет больший оверхед.
Во-первых если не использовать keep-alive то браузер будет создавать тсп-соединение для каждого http-запроса и здесь http выходит намного тяжелее.
Во-вторых передача статуса и хедеров в текстовый формате для каждого запроса в итоге имеет больший размер и оверхед и это особенно видно при передаче небольших порций данных (с вебсокетами это может быть десяток байт когда же с http запрос будет занимать от сотни байт)
В-третих с http у браузеров есть ограничение на количество одновременных запросов (чего нет с вебсокетами).
В-четвертых проблема идемпотентности с http решается намного сложнее чем с вебсокетами (с http порядок запросов не гарантируются и они на сервер могут прийти в другом порядке чем были отправлены из клиента, когда же с вебсокетами у нас есть строгий порядок сообщений)
Ну и наконец вебсокеты это очень простая спецификация (по сути хедер с размером сообщения поверх тсп-протокола) и написать парсер вебсокетов можно за пару часов (формат фрейма объясняют даже для новичков) в то время как написать парсер http (не говоря уже про http2) это приключение на месяц учитываю кучу разнообразных нюансов самого текстового http формата, так и специфику корректно обработки различных хедеров (в частности keep-alive)
А все эти REST/RPC PUT/DELETE/OPTIONS/GET/POST и прочее это просто уровни абстракции придуманные самими разработчиками для удобства. Если писать большое приложение на WebSocket-ах вы придумаете свои такие же.
Нет, такого беспорядка и дилеммы выбора как с http не будет, зачем? Зачем нужны эти имена методов и статусы кодов ошибок если можно просто передать скажем объект {action: "createProject", params: [...]} и вернуть объект {error: "..." | null, data: "..." | null} и вебсокет-обработчик на сервере просто вызовет нужную функцию и уже в самой функции будет происходит вся необходимая обработка — будь то получение (GET) или обновление данных (POST, PUT) или удаление (DELETE) или когда все эти действия происходят одновременно вместе с if-ами и циклами для батч-обработки каких-то данных (что просто не имеет соответствия "семантическим" методам в случае http). То есть исходная задача — вызывать какую-то процедуру на сервере и передать ей нужные параметры чтобы она обработала "запрос" и получила/обновила нужные данные в бд и вернула ответ назад с вебсокетами решается на порядок проще чем с http (где вызов нужной процедуры почему-то додумались делать через ручное придумывание и конфигурацию имен для роутов с маппингом на path/query http-запроса)
А объясните пожалуйста зачем какому-то условному новичку (который примерно понимает как работает веб, как ходят запросы и что такое tcp) использовать все эти express/koa/fastify/nest/etc nodejs-фреймворки? Вот стоит перед новичком задача — со стороны клиента получить какие-то объекты с данными из бд или отправить объект с метаданными (для того чтобы изменить данные в бд). Новичок и так будет знать что вся информация в вебе ходит поверх тсп-протокола (который уже обеспечивает целостность данных при передаче), но чистый тсп в браузерах недоступен и браузеры предлагают два варианта — http или websockets
И какой самый простой способ решить эту задачу? Зачем этому новичку следует выбирать всякие express/fastify/nest-фреймворки со всякими непонятными middleware/сontrollers поверх http/rest подходов со всякими тонкостями/нюансами/дилеммами выбора методов (post vs put), способа передачи информации (path/query/headers/body) и выбора кодов для ошибок, зачем все это если можно просто установить вебсокет-соединение и просто пересылать нужные объекты/json от клиента к серверу и обратно. То есть исходная задача (установка транспорта между клиентом и сервером чтобы пересылать данные) с вебсокетами решается на порядок проще без всяких фреймворков чем c этими http/rest-фреймворками вроде express/fastify/nest и со стороны новичка становится совершенно непонятно зачем выбирать тот же fastify вместо вебсокетов
Вот он — триумф вертикального масштабирования! In-memory база данных поверх такого процессора способна будет обрабатывать десятки, сотни миллионов или возможно даже миллиард serializable транзакций в секунду и способна заменить сотни/тысячи серверов (и тот огромный оверхед при реализации распределенных транзакций в случае горизонтального масштабирования) определенно точно найдет своего покупателя.
Интересно как в этом процессоре работает механизм cache-coherence который обеспечивает CAS ("compare-and-swap") и другие атомарные обновления памяти? Cache-coherence это другими словами реализация атомарного бродкаста и поскольку это и так самая сложная часть при проектировании современных процессоров то здесь при 850 тысяч ядрер и возможном отказе этих ядер по отдельности проектировщики должны были выйти на уровень распределенных систем (интересно они реализовали paxos в железе?)
а чем плох вариант просто вызывать в цикле функцию вроде parseNextHttpRequest(buf) с передачей буфера и получением словаря http-хедеров и значений (а также статуса и тела). Вполне себе органично вписывается в тот пример кода выше где вместо вызова do_use_fd(..) будет вызов parseNextHttpRequest а потом уже обработка самого http-запроса вызовом еще одной функции
Я правильно понял что основной посыл статьи или видео в том что язык нужно начинать с изучения грамматики (принципы построения языка) и не слушать тех кто говорит что лучше вместо грамматики пообщаться с носителями языка ?
А чем плох вариант просто пробросить системный вызов epoll в линуксе? Linux уже предоставляет возможности асинхронного io виде синхронного вызова epoll_wait в бесконечном цикле. Вот я нашел такую библиотеку (https://github.com/chopins/php-epoll), какие есть недостатки у такого подхода ?
Понятно что это только работа с голым tcp но ведь можно подключить какую-нибудь библиотеку которая будет парсить из tcp-потока http-запросы и таким образом получим на php асинхронный http-сервер который будет не хуже чем в NodeJS (и также это избавляет от необходимости использовать Apache или Nginx перед php)
Сколько раз ревьюеру (который видит этот кусок кода первый раз) нужно будет промотать глазами чтобы понять что происходит в коде?
1) видим строчку COMPONENT_MAP[user.type] — ага, нужно найти взглядом эту переменную из внешнего скоупа и понять что там хранится,
2) видим строчку рендера какого-то компонента <Component name={user.name} /> — опять нужно найти взглядом переменную из внешнего скоупа и понять что записано в переменную Component.
3-6) и наконец по значениям-ссылкам на три компонента которые были записаны в COMPONENT_MAP мы теперь должны найти каждый компонент и понять что он рендерит
Сколько раз в этой версии разработчику нужно будет мотать глазами чтобы понять что происходит в коде? Не проще ли становится код когда вообще не нужно мотать глазами? Не является ли вторая версия более "декларативной" ?
А что вы скажете насчет веб-компонентов? Разве они были придуманы не для того чтобы избавиться от проблемы ограниченного набора и неоднозначности "семантических" html-тегов? Почему вместо разнообразных <div>, <span>, <header>, <footer>, <main>, <section>, <article>, <h1>, <ul>, etc нельзя использовать кастомные веб-компоненты которые будут лучше подходить по семантике и функционалу к конкретной ситуации и лучше соответствовать дизайн-системе и семантически-функциональной структуре сайта/веб-приложения?
А кто-нибудь знает почему не взлетела идея с FPGA? Ведь тогда каждая программа могла бы сама определять наиболее эффективные для своего исполнения инструкции, кеши и пайплайны. Или, например, с++/rust компилятор после всевозможных оптимизаций мог бы компилировать программу не в набор ассемблерных инструкций а сразу в схему транзисторов и связей которая будет максимально эффективна для конкретной программы
А почему такой скромный заголовок? Судя по тому что в википедии написано что температура ядра солнца всего лишь 15 млн градусов то достижение в 100 млн градусов надо было назвать как-нибудь "Ученые создали и двадцать секунд удерживали самое горячее вещество в солнечной системе, в 7 раз горячее солнца!!!"
А вообще цифры конечно впечатляют и сразу возникает такой вопрос почему так несимметрично — значит если нагревать так и до 100 млн можно а если охлаждать то всего лишь до -273 градусов и больше нельзя (так как абсолютный ноль), разница аж целых 6 порядков!
Ну вот я использую голый реакт и получается даже более удобно чем с mobx, вот пример — https://codesandbox.io/s/competent-engelbart-cltwg. Нет никакой магии геттеров-сеттеров или прокси-объектов, просто вызываем функцию актуализации когда нужно актуализировать view с состоянием. Есть и недостаток в виде менее эффективного обновления (реакт будет делать diff всего приложения при изменении состояния). Но тормоза появляются лишь на больших приложениях (> 10к дом-нод) что встречается нечасто и для 99% mvp-приложений можно обойтись без mobx (и потом можно легко подключить его только в случае появления тормозов diff-механизма реакта).
Сравнение некорректное. Java это язык а нода это рантайм (конкретная реализация взаимодействия с IO операционной системы). И скорость ноды и этой хваленый event loop и т.д — это все заслуга системного IO операционной системы — например на линуксе это системный вызов epoll_wait(..) — который позволяет одним потоком обслуживать много сокетов. Это значит что аналогичную эффективность NodeJS (скорости работы с io и обслуживание одним потоком многих tcp/http запросов) можно получить на всех популярных языках — не только на java но и например на php — достаточно всего лишь прокинуть системные вызовы epoll_wait/epoll_create/… в интерпретатор или компилятор языка.
Как известно, в Node.js реализовано однопоточная событийно-ориентированная модель. Это отлично подходит для большого количества запросов, но совершенно не годится для распараллеливания вычислений или реализации сложной бизнес-логики.
Вы серьезно? Тогда такой вопрос — как вы собираетесь поддерживать атомарность при выполнении сложной бизнес-логики? Многопоточная модель это прямой путь к race-conditions и неконсистетности данных. Вы знаете что в базах данных (включая postgres, mysql) по умолчанию не включен serializable уровень изоляции и поэтому любую бэкенд-логику которая работает с бд отдельными запросами нужно врапить в эти транзкции (от начала и до конца) иначе рано или поздно у вас появятся race-conditions и неконсистентность данных (https://www.youtube.com/watch?v=5ZjhNTM8XU8)?
А теперь вопрос — какой тип бд позволяет обрабатывать транзакции с любой логикой (запросы к различным таблицам, включая условия и циклы) c seriazlizable-уровнем изоляции со скоростью > 100к транзакций в секунду? Вы не поверите но это такие базы данных которые выполняют все транзакции в одном потоке и вполне могут быть написаны на Node.js. Яркий пример такой бд — это Tarantool (https://www.youtube.com/watch?v=yrTF3qH8ey8)
А что касается скорости одного потока javascript — то он вполне находится на уровне с++ (если не относиться наплевательски на советы по производительности) — вот доклад где сравнивается с++ и js — https://www.youtube.com/watch?v=UJPdhx5zTaw и js всего лишь на 17% медленнее чем с++ с O3-флагом оптимизации (и это было еще в 2012 году)
Вспомнил ваш ник в статьях CodeRush :) Вы случайно не в курсе что изменилось с тех пор? Насколько сложно сейчас вирусу с правами админа или рута пережить переустановку ос? И кстати если ли смысл как-то защищаться на этом уровне? Мол из-за таких защит сам юзер (имея права админа) уже не сможет просто обновить bios и перезагрузить — ему придется делать дополнительные манипуляции (писать на флешку, зажимать горячие клавиши при включении и т.д). И если мы не хотим доставлять неудобств юзеру то появляются такие уже мысли — мол пусть операционные системы становятся менее дырявыми и делают гранулярные права на те или иные возможности (как в ios и android), и если уж программа получила права рута так лишь бы не перезатерла одноразовые fuses в биос — чтобы можно было при переустановке (или покупке б/у) вычистить/сбросить весь перезаписываемый код в биос (и других разнообразных firmware-областях)
Основная проблема заключается в том, что при вводе каждой буквы в соответствующих полях вся форма будет перерисовываться, что влечет за собой проблемы с производительностью, особенно на мобильных устройствах.
Вы серьезно? Знаете что я делаю когда мне нужно отобразить сложные формы как в вашем случае когда у нас "в общей сложности более 80 разных полей"?
Я не использую никакие стейт-менеджеры или библиотеки для форм я просто использую обычный реакт и в каждом обработчике поля onChange пишу примерно такое
<input onChange={(e)=>{
AppState.form.someField = e.target.value;
//валидация или другая логика
actualize() //однострочный хелпер который вызывает ReactDOM.render(<App/>, el)
}}/>
Увидев вызов ReactDOM.render(<App/>), вы наверное подумаете "о боги, это же перерисовка всего приложения при вводе каждой буквы!". Поэтому позвольте мне напомнить что такое "перерисовка" в терминах реакта. В реакте "перерисовка" это просто рекурсивное сравнение двух деревьев js-объектов чтобы изменить в html/dom только то что отличается. Сравнение очень быстрое — никаких медленных обращений к дом-элементам, алгоритм линейный (просто спуск по дереву объектов и сравнение свойств с соответствующим объектом от предыдущего вызова перерисовки), сам javascript умеет компилироваться в ассеблер и его скорость на уровне с++ или даже быстрее (https://www.youtube.com/watch?v=UJPdhx5zTaw). В общем за 1мс можно "перерисовать" или точнее сравнить дерево из 50к объектов. И на этом фоне ваши желания оптимизировать вызов "перерисовки" отдельных компонентов для формы из всего лишь 100 полей выглядят забавно
При этом архитектуру нужно было заложить с запасом прочности, в расчете на будущее расширение
И поэтому вы выбрали микросервисы? Вы не видите в этом противоречие? Микросервисы это изоляция по функционалу и по данным (каждый микросервис должен хранить данные в своей базе данных иначе считается что это не настоящие микросервисы). Ок, вы построили архитектуру и разбили по микросервисам — например платежами/переводами занимается один сервис а данными юзеров занимается второй сервис. Правильно? А потом на следующий день прилетает задача — вот мы хотим добавить программу лояльности и начислять юзеру какие-то баллы за переводы. И теперь для реализации этой задачи микросервису переводов нужно общаться с микросервисом который хранит данные юзеров. А теперь вопрос — как вы будете решать race-conditions и атомарное выполнение этой бизнес-логики? Речь не только про потерю связи, логику retry-ев на транспортном уровне (https://habr.com/ru/company/yandex/blog/442762) а про более фундаментальную проблему консистентной обработки данных и serializable уровня изоляции транзакций — https://www.youtube.com/watch?v=5ZjhNTM8XU8
В общем микросервисы можно применять только когда проект уже устоялся и не планирует расширяться, иначе добавление нового функционала имеет тенденцию увеличивать связность данных а это в свою очередь требует атомарного выполнения бизнес-логики которая обращается к разным микросервисам и реализации распределенных serializable-транзакций (иначе привет race-conditions и неконсистетность данных и дыры в безопасности)
Зачем такие сложности с создаем новой колонки и постепенной миграцией? Почему бы просто не задать всем колонкам уникальное имя которое никогда не захочется поменять (случайный айдишник) а уже в коде хранить соответствие имя -> id при работе с этой бд. Тогда переименование колонки сведется к простейшей операции замены одного имени на другое в коде вообще без каких-либо затрат со стороны бд
вы только представляете а кто-то уже так делает и зарабатывает миллионы — вот один комментарий на HN который недавно набрал популярность в твиттере https://news.ycombinator.com/item?id=27454589
Насчет ангуляра не скажу но с реактом я применяю другой подход — просто пишу функции инлайном и таким образом вообще избавляюсь от диллемы именования функций и заодно очень просто и круто решается вопрос сематического соответствия кнопки и обработчика — вот есть кнопка а значит обработчик функции будет на этой кнопке (или наоборот — если видишь обработчик кнопки то и кнопка будет рядом)
Тут можно сказать мол "да ты захламляешь шаблон как такое вообще читать и поддерживать когда мол верстка в перемешку с логикой?" на что я отвечу "а code folding (сворачивание) в редакторе кода для кого придумали?" Если хотите видеть/редактировать только верстку то можно легко свернуть весь код обработчиков и увидеть чистый шаблон. И наоборот — если хотите посмотреть что делает какая-то кнопка то перемещаем мышку влево на пару сантиметров и кликаем-раскрываем обработчик кнопки.
Это намного удобнее чем переходить в отдельный файл или скроллить экран вверх-вниз (когда выносим обработчик функции в другое место). Это также удобно в поддержке — если допустим у нас поменялся дизайн/ux/логика и поменялась верстка в результате которой нужно удалить какой-то блок вместе с кнопкой то я удаляю нужный кусок верстки и вместе с этим удалится и обработчик этой кнопки поскольку он записан инлайном — мне не нужно беспокоится а не удалил/почистил ли я различные обработчики в другом файле или других местах по коду
И то же самое с добавлением какой-то фичи — я пишу кнопку и тут же пишу обработчик этой кнопки рядом и мне не нужно думать над тем куда вынести этот обработчик а главное — какое имя придумать этому обработчику. И также это удобно при ревью кода — когда добавляется какая-то фича то в git diff видишь изменения только в одном месте а не размазаны по кусочкам на кучу файлов/мест (верстка в одном месте, обработчик в другом месте и т.д)
Как вебсокеты могут быть более тяжёлой штукой чем http-запросы? Вы понимаете как работает http? HTTP-запрос это точно такое же тсп-соединение как и вебсокеты и ничем не легче по "тяжести". И если интернет-соединение нестабильное то http-запрос будет точно также обрываться с ошибкой как и вебсокет-соединение (и соотвественно нужно делать повторный запрос/установку соединения), в этом плане я вообще не вижу никакой разницы.
А вот во многих моментах http намного хуже и имеет больший оверхед.
Во-первых если не использовать keep-alive то браузер будет создавать тсп-соединение для каждого http-запроса и здесь http выходит намного тяжелее.
Во-вторых передача статуса и хедеров в текстовый формате для каждого запроса в итоге имеет больший размер и оверхед и это особенно видно при передаче небольших порций данных (с вебсокетами это может быть десяток байт когда же с http запрос будет занимать от сотни байт)
В-третих с http у браузеров есть ограничение на количество одновременных запросов (чего нет с вебсокетами).
В-четвертых проблема идемпотентности с http решается намного сложнее чем с вебсокетами (с http порядок запросов не гарантируются и они на сервер могут прийти в другом порядке чем были отправлены из клиента, когда же с вебсокетами у нас есть строгий порядок сообщений)
Ну и наконец вебсокеты это очень простая спецификация (по сути хедер с размером сообщения поверх тсп-протокола) и написать парсер вебсокетов можно за пару часов (формат фрейма объясняют даже для новичков) в то время как написать парсер http (не говоря уже про http2) это приключение на месяц учитываю кучу разнообразных нюансов самого текстового http формата, так и специфику корректно обработки различных хедеров (в частности keep-alive)
Нет, такого беспорядка и дилеммы выбора как с http не будет, зачем? Зачем нужны эти имена методов и статусы кодов ошибок если можно просто передать скажем объект
{action: "createProject", params: [...]}
и вернуть объект{error: "..." | null, data: "..." | null}
и вебсокет-обработчик на сервере просто вызовет нужную функцию и уже в самой функции будет происходит вся необходимая обработка — будь то получение (GET) или обновление данных (POST, PUT) или удаление (DELETE) или когда все эти действия происходят одновременно вместе с if-ами и циклами для батч-обработки каких-то данных (что просто не имеет соответствия "семантическим" методам в случае http). То есть исходная задача — вызывать какую-то процедуру на сервере и передать ей нужные параметры чтобы она обработала "запрос" и получила/обновила нужные данные в бд и вернула ответ назад с вебсокетами решается на порядок проще чем с http (где вызов нужной процедуры почему-то додумались делать через ручное придумывание и конфигурацию имен для роутов с маппингом на path/query http-запроса)А объясните пожалуйста зачем какому-то условному новичку (который примерно понимает как работает веб, как ходят запросы и что такое tcp) использовать все эти express/koa/fastify/nest/etc nodejs-фреймворки? Вот стоит перед новичком задача — со стороны клиента получить какие-то объекты с данными из бд или отправить объект с метаданными (для того чтобы изменить данные в бд). Новичок и так будет знать что вся информация в вебе ходит поверх тсп-протокола (который уже обеспечивает целостность данных при передаче), но чистый тсп в браузерах недоступен и браузеры предлагают два варианта — http или websockets
И какой самый простой способ решить эту задачу? Зачем этому новичку следует выбирать всякие express/fastify/nest-фреймворки со всякими непонятными middleware/сontrollers поверх http/rest подходов со всякими тонкостями/нюансами/дилеммами выбора методов (post vs put), способа передачи информации (path/query/headers/body) и выбора кодов для ошибок, зачем все это если можно просто установить вебсокет-соединение и просто пересылать нужные объекты/json от клиента к серверу и обратно. То есть исходная задача (установка транспорта между клиентом и сервером чтобы пересылать данные) с вебсокетами решается на порядок проще без всяких фреймворков чем c этими http/rest-фреймворками вроде express/fastify/nest и со стороны новичка становится совершенно непонятно зачем выбирать тот же fastify вместо вебсокетов
Вот он — триумф вертикального масштабирования! In-memory база данных поверх такого процессора способна будет обрабатывать десятки, сотни миллионов или возможно даже миллиард serializable транзакций в секунду и способна заменить сотни/тысячи серверов (и тот огромный оверхед при реализации распределенных транзакций в случае горизонтального масштабирования) определенно точно найдет своего покупателя.
Интересно как в этом процессоре работает механизм cache-coherence который обеспечивает CAS ("compare-and-swap") и другие атомарные обновления памяти? Cache-coherence это другими словами реализация атомарного бродкаста и поскольку это и так самая сложная часть при проектировании современных процессоров то здесь при 850 тысяч ядрер и возможном отказе этих ядер по отдельности проектировщики должны были выйти на уровень распределенных систем (интересно они реализовали paxos в железе?)
а чем плох вариант просто вызывать в цикле функцию вроде
parseNextHttpRequest(buf)
с передачей буфера и получением словаря http-хедеров и значений (а также статуса и тела). Вполне себе органично вписывается в тот пример кода выше где вместо вызоваdo_use_fd(..)
будет вызовparseNextHttpRequest
а потом уже обработка самого http-запроса вызовом еще одной функцииЯ правильно понял что основной посыл статьи или видео в том что язык нужно начинать с изучения грамматики (принципы построения языка) и не слушать тех кто говорит что лучше вместо грамматики пообщаться с носителями языка ?
А чем плох вариант просто пробросить системный вызов epoll в линуксе? Linux уже предоставляет возможности асинхронного io виде синхронного вызова epoll_wait в бесконечном цикле. Вот я нашел такую библиотеку (https://github.com/chopins/php-epoll), какие есть недостатки у такого подхода ?
Понятно что это только работа с голым tcp но ведь можно подключить какую-нибудь библиотеку которая будет парсить из tcp-потока http-запросы и таким образом получим на php асинхронный http-сервер который будет не хуже чем в NodeJS (и также это избавляет от необходимости использовать Apache или Nginx перед php)
Серьезно? Что же, давайте более подробно проанализируем этот кусок кода
Сколько раз ревьюеру (который видит этот кусок кода первый раз) нужно будет промотать глазами чтобы понять что происходит в коде?
1) видим строчку
COMPONENT_MAP[user.type]
— ага, нужно найти взглядом эту переменную из внешнего скоупа и понять что там хранится,2) видим строчку рендера какого-то компонента
<Component name={user.name} />
— опять нужно найти взглядом переменную из внешнего скоупа и понять что записано в переменную Component.3-6) и наконец по значениям-ссылкам на три компонента которые были записаны в COMPONENT_MAP мы теперь должны найти каждый компонент и понять что он рендерит
А теперь сравним это с такой версией
Сколько раз в этой версии разработчику нужно будет мотать глазами чтобы понять что происходит в коде? Не проще ли становится код когда вообще не нужно мотать глазами? Не является ли вторая версия более "декларативной" ?
А что вы скажете насчет веб-компонентов? Разве они были придуманы не для того чтобы избавиться от проблемы ограниченного набора и неоднозначности "семантических" html-тегов? Почему вместо разнообразных
<div>, <span>, <header>, <footer>, <main>, <section>, <article>, <h1>, <ul>, etc
нельзя использовать кастомные веб-компоненты которые будут лучше подходить по семантике и функционалу к конкретной ситуации и лучше соответствовать дизайн-системе и семантически-функциональной структуре сайта/веб-приложения?А кто-нибудь знает почему не взлетела идея с FPGA? Ведь тогда каждая программа могла бы сама определять наиболее эффективные для своего исполнения инструкции, кеши и пайплайны. Или, например, с++/rust компилятор после всевозможных оптимизаций мог бы компилировать программу не в набор ассемблерных инструкций а сразу в схему транзисторов и связей которая будет максимально эффективна для конкретной программы
А почему такой скромный заголовок? Судя по тому что в википедии написано что температура ядра солнца всего лишь 15 млн градусов то достижение в 100 млн градусов надо было назвать как-нибудь "Ученые создали и двадцать секунд удерживали самое горячее вещество в солнечной системе, в 7 раз горячее солнца!!!"
А вообще цифры конечно впечатляют и сразу возникает такой вопрос почему так несимметрично — значит если нагревать так и до 100 млн можно а если охлаждать то всего лишь до -273 градусов и больше нельзя (так как абсолютный ноль), разница аж целых 6 порядков!
Ну вот я использую голый реакт и получается даже более удобно чем с mobx, вот пример — https://codesandbox.io/s/competent-engelbart-cltwg. Нет никакой магии геттеров-сеттеров или прокси-объектов, просто вызываем функцию актуализации когда нужно актуализировать view с состоянием. Есть и недостаток в виде менее эффективного обновления (реакт будет делать diff всего приложения при изменении состояния). Но тормоза появляются лишь на больших приложениях (> 10к дом-нод) что встречается нечасто и для 99% mvp-приложений можно обойтись без mobx (и потом можно легко подключить его только в случае появления тормозов diff-механизма реакта).
Сравнение некорректное. Java это язык а нода это рантайм (конкретная реализация взаимодействия с IO операционной системы). И скорость ноды и этой хваленый event loop и т.д — это все заслуга системного IO операционной системы — например на линуксе это системный вызов epoll_wait(..) — который позволяет одним потоком обслуживать много сокетов. Это значит что аналогичную эффективность NodeJS (скорости работы с io и обслуживание одним потоком многих tcp/http запросов) можно получить на всех популярных языках — не только на java но и например на php — достаточно всего лишь прокинуть системные вызовы epoll_wait/epoll_create/… в интерпретатор или компилятор языка.
Вы серьезно? Тогда такой вопрос — как вы собираетесь поддерживать атомарность при выполнении сложной бизнес-логики? Многопоточная модель это прямой путь к race-conditions и неконсистетности данных. Вы знаете что в базах данных (включая postgres, mysql) по умолчанию не включен serializable уровень изоляции и поэтому любую бэкенд-логику которая работает с бд отдельными запросами нужно врапить в эти транзкции (от начала и до конца) иначе рано или поздно у вас появятся race-conditions и неконсистентность данных (https://www.youtube.com/watch?v=5ZjhNTM8XU8)?
А теперь вопрос — какой тип бд позволяет обрабатывать транзакции с любой логикой (запросы к различным таблицам, включая условия и циклы) c seriazlizable-уровнем изоляции со скоростью > 100к транзакций в секунду? Вы не поверите но это такие базы данных которые выполняют все транзакции в одном потоке и вполне могут быть написаны на Node.js. Яркий пример такой бд — это Tarantool (https://www.youtube.com/watch?v=yrTF3qH8ey8)
А что касается скорости одного потока javascript — то он вполне находится на уровне с++ (если не относиться наплевательски на советы по производительности) — вот доклад где сравнивается с++ и js — https://www.youtube.com/watch?v=UJPdhx5zTaw и js всего лишь на 17% медленнее чем с++ с O3-флагом оптимизации (и это было еще в 2012 году)
Вспомнил ваш ник в статьях CodeRush :) Вы случайно не в курсе что изменилось с тех пор? Насколько сложно сейчас вирусу с правами админа или рута пережить переустановку ос? И кстати если ли смысл как-то защищаться на этом уровне? Мол из-за таких защит сам юзер (имея права админа) уже не сможет просто обновить bios и перезагрузить — ему придется делать дополнительные манипуляции (писать на флешку, зажимать горячие клавиши при включении и т.д). И если мы не хотим доставлять неудобств юзеру то появляются такие уже мысли — мол пусть операционные системы становятся менее дырявыми и делают гранулярные права на те или иные возможности (как в ios и android), и если уж программа получила права рута так лишь бы не перезатерла одноразовые fuses в биос — чтобы можно было при переустановке (или покупке б/у) вычистить/сбросить весь перезаписываемый код в биос (и других разнообразных firmware-областях)
У вас в таком коде
не учитывается фрагментация когда буфер полученный в обработчике 'data'-события может быть длиной вплоть до одного байта
Вы серьезно? Знаете что я делаю когда мне нужно отобразить сложные формы как в вашем случае когда у нас "в общей сложности более 80 разных полей"?
Я не использую никакие стейт-менеджеры или библиотеки для форм я просто использую обычный реакт и в каждом обработчике поля onChange пишу примерно такое
Увидев вызов ReactDOM.render(<App/>), вы наверное подумаете "о боги, это же перерисовка всего приложения при вводе каждой буквы!". Поэтому позвольте мне напомнить что такое "перерисовка" в терминах реакта. В реакте "перерисовка" это просто рекурсивное сравнение двух деревьев js-объектов чтобы изменить в html/dom только то что отличается. Сравнение очень быстрое — никаких медленных обращений к дом-элементам, алгоритм линейный (просто спуск по дереву объектов и сравнение свойств с соответствующим объектом от предыдущего вызова перерисовки), сам javascript умеет компилироваться в ассеблер и его скорость на уровне с++ или даже быстрее (https://www.youtube.com/watch?v=UJPdhx5zTaw). В общем за 1мс можно "перерисовать" или точнее сравнить дерево из 50к объектов. И на этом фоне ваши желания оптимизировать вызов "перерисовки" отдельных компонентов для формы из всего лишь 100 полей выглядят забавно
И поэтому вы выбрали микросервисы? Вы не видите в этом противоречие? Микросервисы это изоляция по функционалу и по данным (каждый микросервис должен хранить данные в своей базе данных иначе считается что это не настоящие микросервисы). Ок, вы построили архитектуру и разбили по микросервисам — например платежами/переводами занимается один сервис а данными юзеров занимается второй сервис. Правильно? А потом на следующий день прилетает задача — вот мы хотим добавить программу лояльности и начислять юзеру какие-то баллы за переводы. И теперь для реализации этой задачи микросервису переводов нужно общаться с микросервисом который хранит данные юзеров. А теперь вопрос — как вы будете решать race-conditions и атомарное выполнение этой бизнес-логики? Речь не только про потерю связи, логику retry-ев на транспортном уровне (https://habr.com/ru/company/yandex/blog/442762) а про более фундаментальную проблему консистентной обработки данных и serializable уровня изоляции транзакций — https://www.youtube.com/watch?v=5ZjhNTM8XU8
В общем микросервисы можно применять только когда проект уже устоялся и не планирует расширяться, иначе добавление нового функционала имеет тенденцию увеличивать связность данных а это в свою очередь требует атомарного выполнения бизнес-логики которая обращается к разным микросервисам и реализации распределенных serializable-транзакций (иначе привет race-conditions и неконсистетность данных и дыры в безопасности)