Как стать автором
Обновить
4
0
Алексей Повар @wert_lex

Server Side Developer

Отправить сообщение

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


Код в первую очередь должен быть читабелен человеком.

Еще с момента анонса беспроводных наушников от Apple мучает вопрос — современный Bluetooth 4.x принципиально может передать звук без потерь?
Вроде бы не может, и потому использует разные кодеки вроде aptX, которые пережимают декодированный на хосте аудиопоток. В результате получаем двойное кодирование с потерями.
Так ведь?

Вопрос. Если все worker-ы симметричные, то не проще было ли писать приложение без cluster (особенно учитывая что усложнять пример не хотелось), а запускаться потом через PM2? Там и gracefull reload, и cluster, и auto restart, и даже логи в реальном времени.


И таки для request request-promise, которые для тестирования кода, лучше таки --save-dev использовать.

Если рассматривать сферический DOM в вакууме, то да, React == Shadow DOM + DOM, а потому медленнее.
Но на самом деле речь ведь о скорости и сложности, с которой DOM переводится из состояния A в состояние B.
Да, эффективное использование DOM всегда быстрее, но сложность в таком случае может расти очень быстро, если речь идёт о чем-то более сложном, чем обновление properties на узлах. И тут внезапно может оказаться, что толковый подход это уже половина реактовского dom reconciliation, только глючная и никем не тестированная.

Например, знаменитое 0.1 + 0.2 не равняется 0.3 в связи с тем, что в JavaScript нет встроенного десятичного типа.

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


Loopback

Могу поделится своим негативным опытом. Дело было год назад. Речь о REST API сервере.
Штука в целом прикольная — ты такой накидал конфигурацию, а оно такой быстренько поехало. Ну почти.
Только хвалёный ORM не может делать джойны в БД. Ну и эпизодически выплывали интересные артефакты, связанные с тем, что местному ORM-у, ну скажем так, есть еще куда расти.
Справедливости ради, архитектурно там предусмотрены дырки, куда можно засунуть правильную реализацию джойнов и всего этого database-related добра с учетом специфики конкретной базы, но на тот момент готовых компонент для этого не нашлось.
Ну и в ряде мест оно необъяснимо тормозило. В документации об этом разумеется не писали, но дебаг приводил опять же в ORM.


В результате переписали за месяц на Express + Mongoose. Стало лучше, быстрее, и главное проще и более предсказуемо.

Я вот либо что-то упустил в самых основах, либо это нечто совсем недавно появилось. Но хм… это не создает новой области видимости. Если не сложно, можно ссылку на пример? Вот gist с прямым примером: https://gist.github.com/wertlex/b97115e0f2fe0bc023297f6b2db8edd5

В целом — да, но в принципе такой штуки можно и достичь простой оберткой function -> react class. Но за ссылку спасибо.

Насчёт 7. switch в javascript зло конечно дикое, но из него можно изобразить что-то вроде паттерн матчинга для бедных. Для очень бедных.


switch(true) {
  case type === "click" && something.isDefined() === true:
    return "It was click";
case type === "mouseenter" && somethingElse.isDefined() === true:
    return "It was mouseenter";
default:
    return console.warn(`No case for event type "${type}"`);

На мой взгляд даже в таком виде это сильно симпатичнее цепочки if-else-if. Но дно достигается, конечно, в момент объявления переменной в любом case. Никакие let и const не спасают — scope у всех один.

О, ну тут всё достаточно просто.
Что происходит, когда надо перерисовать компонент? Вызывается метод shouldComponentUpdate(nextProps, nextState): Boolean.

Если метод вернет false, то всё дерево компонентов, которое строится в результате работы метода render() останется нетронутым — это называется short circuit. Т.е. ты как-бы говоришь реактовскому движку «спокойно парень, я уверен, ничего не изменилось», и реакт пропускает целиком все поддерево, которое растет из этого компонента.

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

Мораль: правильно написанный (но не всегда :) ), shouldComponentUpdate может сильно ускорить перерисовку.
И вот этого метода в functional components нету, хотя было бы круто, если бы был.
Stateless functions — очень удобная в быту штука. Но, к сожалению, пока не умеет shouldComponentUpdate для того, чтобы проверить самому props, сделать short circuit и не рендерить всех детей. А было бы классно, в некоторых случаях top-down rendering стал бы ну очень простым и дешевым.
Но вроде бы обещают сделать.
Вот у меня вопрос немного не по теме сравнения.
А когда уже в Scala завезут нормальный, Scala-inspired веб-фреймворк? Что-то уровня нодовского Express, только с батарейками из Scala.
Сейчас объясню, и если не прав — поправьте.
Есть Netty, который очень низкоуровневый, несомненно хорош, но для простенького REST API в десяток методов и две формы — это явно слишком низкоуровневый инструмент.

Есть Play2, в который всё подряд понапихали уже. А в качестве вишенки на торте вкорячили Runtime DI (да, в типобезопасный язык; да, знаю про интероп с Java). Хотя, вроде бы можно там как-то устроить себе Compile Time DI, но выглядит это всё как-то сложно и странно. Зато тут очень классная Json библиотека.

Есть/был Spray. Который прикольно лег на модель акторов, и на котором настолько же невозможно писать читаемый код. Spray, который теперь больше не развивается, а стал, akka-http, и где-то год назад оно только более-менее завелось до того состояния, чтобы им не страшно было пользоваться.

Есть/был(?) Scalatra. Который выглядел так, будто неплохо зайдет для наколенного творчества, но последняя версия была 20 декабря 2015.

Ну вот теперь вопрос: куда бежать-то? Play кажется повернул куда-то не туда. Http streaming вроде завезли, но во всяких мелких Rest API обычно хватает ровно одного chunk-а. Spray из неплохой идеи и паршивой реализации как-то так и не расцвёл в готовое решение (или расцвёл?).
Да, а еще lightbend есть, а scala 2.12 — нет.
Лапша решается промисами, потому что позволяет избежать nesting. В целом суть одна, но промисы при этом — мало того что удобная обертка, но еще и эдакий кирпичик асинхронного строения.
Поделюсь своим опытом. Примерно год на node.js. Достаточно активно писал на Scala. С JS знаком был на уровне $.ajax(...).

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

Второе — модули. Да, их на каждый чих и случай жизни, плохие, средние, глючные, но они уже тут и работают. Иногда текут, да. Но, если мы говорим о сервер-сайде, это не то, чтобы прям плюс, но в этом… ну что-ли есть положительная черта. Это тебя готовит к let it crash, что ли. Только crash у тебя не изолированный как в Erlang, а на уровне приложения. Как справедливо заметили cluster и pm2 тут как раз для этого.

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

Третье — JS, достаточно простой, и, черт возьми, выразительный язык. Сейчас фанаты Lisp, конечно поперхнулись, но JS уровня ES2015 в силу first class citizen functions вполне себе может разные штуки, которые на Java 6 выглядели весьма монструозно. Взять те же Promise. Вполне вписывается в ES5, даже если не завезли изначально.

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

Чего на самом деле не хватает? Нормального pattern matching-а, ну и иногда тоска накатывает из-за отсутствия typesafety. Но в такие моменты я обычно вспоминаю def myFunc[A, B >: C, E:A, D \/ E](a: A, b:B, c:C, d;D, e: E): [A \/ E] и как-то легче становится :)
Ну вообще там весьма неплохо. Если свободное пространство — это поля и березки, то и в самом деле нету. Если сравнивать с мегаполисом вроде Москвы — свободного пространства примерно одинаково. Торговые центры под, на и над землей, прогулочные улицы, парки — есть.
До покупаться в море — порядка часа езды — Sentosa.
Вся ЮВА от силы в двух часах лёта.

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

Насчет места, где не дерут за проезд и паркову… А это где в России проезд стал бесплатный? :)
Статья конечно про РСУБД, но тем не менее поделюсь. Используем Mongo — там с этим все достаточно просто и прямо. Развернули новую БД, прогнали init script если есть необходимость, отработал тест, дропнули базу.
У нас есть юнит тесты для слоя доступа — там на каждый тест поднимается отдельная база, и есть acceptance/functional тесты — там кроме БД поднимается еще и инстанс прилолжения и один инстанс приходится на один test suite, иначе таки да, ожидание становится мучительным.
Стек — node.js, js, express, mongoose.

Весь набор тестов не очень большой ~ 50 unit + 150 functional. Отрабатывают секунд за 20 на Core i5/8Gb/SSD. Все тесты и тест сьюты работают исключительно последовательно.
Хороший вопрос)
А если вычисления есть? Вытаскивать их из ноды и рулить внешним процессом? Причем я не про числодробилку, а про что-то достаточно простое, но не отрабатывающее в течении милисекунды.
Для типичных веб-задач конечно всё это от лукавого, но тем не менее.

Насколько я понимаю под «акторами» на node.js в итоге подразумевалась пачка нодовых процессов, запущенных через cluster, и общающихся через некий внешний event-bus?
Тогда эту штуку конечно по-прежнему можно назвать акторами, но тогда и классы на Java акторы, потому что «получают сообщения» при вызове методов.
Насколько я понимаю, вы из .net?
В JVM есть такая приятная особенность — type erasure. Это значит, что информация о типах из дженериков вся теряется. Это справедливо для любого JVM-based языка. Вот пример из Java: http://stackoverflow.com/a/339708/1040070

Соответственно все штуки, которыми так богата Scala, вроде type constraints (http://stackoverflow.com/a/4870084/1040070), path-dependent types (http://stackoverflow.com/questions/2693067/what-is-meant-by-scalas-path-dependent-types), и тотальное выведение-приведение-проверка типов происходят во время компиляции. В runtime типы дженериков затерты. В Scala есть механизм typetags/classtags, который позволяет держать информацию о типах в runtime, но это скорее опция, и повсеместно оно не используется.
В общем всё это здорово работает и проверяется ровно до того момента, пока вместе компилируется.

Runtime DI подразумевает в свою очередь внедрения кода во время исполнения. Этот код также может быть написан на Scala и быть проверен тайпчекером, но результаты могут оказаться различными — например поменяли List[User] -> List[Profile]. Это вроде бы не сильно тревожно, если у нас полтора модуля для DI, но если мы собираем половину приложения через DI, то как-то это уже начинает не внушать оптимизма. При том, что за все эти тайпчеки мы по-прежнему платим временем во время сборки проекта, да и вообще, нафига городить все эти конструкции из безупречно-типизированного кода, который чуть ли не сам себя пишет (привет макросы из 2.12), если в итоге в рантайме мы будем втаскивать зависимости?

Всё конечно не так плохо, и Scala по прежнему работает, но, кажется последнее время свернула со своего труе-пути и пошла рука об руку с Java. А с учетом нововведений Java 8 возникает логичный вопрос — зачем всё вот это вот хозяйство, если в рантайме у нас зависимости, разработчиков всё еще не так просто найти, если есть Java 8, которая перекрывает 70% того, что есть в Scala, никуда не денется послезавтра и разработчиков под которую можно найти в любом селе необъятной?
1. Почти ничего, кроме того, что Scala — это compile-time typesafe language, в котором этот самый typesafe чуть ли не самая продаваемая и продвигаемая фича, а в одном из самых популярных веб-фреймворков используется runtime DI :)
Не рискну за автора отвечать, но предположу:
отсутствием нормальной библиотеки для http/web? Мы ведь понимаем, что spray — это классный прототип и блестящая идея, а akka-http до сих пор в каком-то не очень понятном состоянии?

Вообще, надо сказать, мне как выходцу и Scala-фанатику это не очень приятно писать, но для того, что описал автор (быстрая реализация хотелок заказчика), связка Akka + Scala + Play 2 (или любой другой фреймворк на этом месте) очень дорогая связка. Мало того, что технологии не совсем мейнстримовые, и разработчиков на Scala надо не только найти, но еще и заставить придерживаться более-менее одного код-стайла, так еще и сам стек куда-то в непонятную сторону поворачивает — Typesafe переименовался в LightBend, Scala 2.12 где-то еще в разработке, Akka Http в каком-то невменяемом состоянии, в Play2 впилили !!runtime Dependency Injection.

Оно конечно всё работает, но вот именно Скальность всего происходящего вызывает вопросы.
Ойвей. Расскажите про акторы на ноде немного подробнее?
Что это такое и с чем его едят в сферическом вакууме понятно. Непонятны технические подробности реализации этого добра на node.js.
Насколько мне известно (а применительно к node.js я начал недавно в эту сторону копать), ничего толкового в духе erlang-а нету, причем по достаточно фундаментальным для node.js причинам. Прежде всего это пресловутая однопоточность выполнения JS. Не существует одного хорошего способа запустить thread: вроде бы был/есть node-threads-a-gogo, который через native код умеет делать что-то очень похожее на нити, но если присмотреться в багтрекер, то можно заметить, что многое добро из node.js в ней не работает (например TypedArrays). Вроде бы есть webworker-threads, но тоже не внушает оптимизма реализация, хотя штука, имхо, очень правильная и в духе ноды.

Cluster тоже не решение, потому что точно также блокирует интерпретатор (да, один из нескольких, запущенных в кластере, но тем не менее).

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

Информация

В рейтинге
Не участвует
Откуда
Россия
Зарегистрирован
Активность