Сообщество nodejs безумно, и судя по тому что в 2016-2017 годах в различных рейтингах JavaScript брал первое место по популярности вытеснив оттуда с небольшим отрывом Java — безумие в последнее время действительно станосится массовым. Казалось бы — не хочешь не кушай, пиши на своём любимом Elixir / Erlang / Lisp / Haskell / любом другом языкое с хорошим дизайном и в ус не дуй, но в текущей ситуации к сожалению это правило перестаёт работать и приходится прилагать некоторые усилия чтобы его соблюдать.
В чём причина популярности такого реально хренового языка как JavaScript? В принципе в том же в чём и причина популярности Java, да и вообще почти всех явлений культуры и общества — в бабле. Когда такие гиганты как Facebook, Google, Microsoft и Twitter методично вливают многомиллионные потоки кровавых долларов в JavaScript инфраструктуру, пишут фреймворки, библиотеки, придумывают стандарты и архитектуры — становится действительно трудно это игнорировать. Настолько сильное вливание бабла вызывает бешеный хайп-драйвен-девелопмент. Работодатель хочет видеть у себя React, Redux, Relay, Realm, Flux, Babel, Webpack / Grunt / Brunch и ещё с десяток модных слов от наших любимых корпораций которых я даже не знаю. И ещё всё это приправлено сверху кучей плагинов для этих же технологий, всех сортов и расцветок из нашего любимого npm. Технологии от корпораций для того чтобы у нас были технологии от корпораций и минифицированный js-бандл весом 15Мб для простого SPA, о да.
В какой-то момент огромный спрос на разработку на действительно ужасном языке породил огромное множество порой довольно странных компиляторов в JavaScript из других, более приемлимых языков. Вполне логично, разработчики мучимые сильнейшим когнитивным диссонансом ( хочу денег, но не хочу JS ) как-то пытались ( и пытаются ) уменьшить боль от разработки на JavaScript. Лично я пробовал довольно много языков из этого списка, какое-то время писал на CoffeeScript подобных языках, наиболее удачный пример LiveScript — из коробки карринг, пайпы, отсутствие дурацких скобочек, точек с запятой, циклов и return-ов. Пробовал даже PureScript — пример компиляции Haskell кода ( с иммутабельностью, монадами и чудесной системой сильных типов ) в JavaScript. На деле же конечно все эти языки не являются коммерчески востребованными по очевидным причинам — нет миллионных вливаний от корпораций в развитие инфраструктуры. Если бы таковые были — зуб даю, все поголовно бы писали на Haskell и рассказывали бы друг другу за чашечкой смузи покручивая спиннер о новых монадах и аппликативных функторах от Facebook.
Казалось бы, меня как backend-девелопера это вообще не должно волновать — пусть будет npm мракобесие на фронтенде, у меня то тут порядочек, кошерное ламповое OTP прямо как в 1986. Но рано было расслабляться — они вырвали JS движок из браузера потащили эту субстанцию на backend, причём с абсолютно серьёзным выражением лица. Ведь одно дело писать на этом языке какой-нибудь SPA, и совсем другое дело какой-нибудь критически важный биллинг. Но JavaScript теперь на backend, отлично.
- однопоточный рантайм ( в 2017 году!!! )
- отсутствие единой системы / стандартов реализации модулей ( опять же, 2017 год на дворе )
- отсутствие единых стандартов структуры проекта ( все творят как хотят, в исходниках бывает очень сложно разобраться )
- слабые типы с неявными ( и порой довольно странными ) преобразованиями
- отсутствие нормальных классов / ООП
- отсутствие единого вменяемого и работающего статического анализатора кода ( добро пожаловать в чудесный мир глупейших ошибок типа undefined is not a function )
- отсутствие вывода типов в самом языке или в каком-либо инструменте
- этот чудесный контекст this ( что это значит this в этом месте кода — объект? функция? )
- абсолютно дурацкая реализация pattern matching ( паттерн матчишь пустой список / объект — без проблем, извлекаешь оттуда undefined, ты же именно это имел ввиду, да? ) и здесь опять привет cannot read property foo of undefined
- отсутствие единой технологии работы с асинхронным кодом — колбэки, примисы, фьючерсы, async ( если в проекте более одной зависимости из npm то гарантированно в коде появятся все из них вперемешку )
- const ( который на самом деле НЕ const )
- абсолютно безумный npm с пакетами качества «братишка я тебе покушать принёс» ( и даже вот с таким )
И это ещё я молчу про субъективный взгляд на раздражающие лично меня особенности типа мутабельности, фигурных скобочек, точек с запятой, return, отсутствия единых стандартов работы со структурами данных, отсутствия макросов или каких-нибудь кастомных инфиксных операторов / функторов.
В общем JavaScript ужасен как ни крути, но он имеет бешеную популярность благодаря баблу и низкому порогу входа. Когда у тебя перед носом водят пачкой зелёных купюр — трудно удержаться, но я держусь. Психическое здоровье дороже. Кстати недавно читал про активность Facebook в области языка Ocaml — так что возможно есть свет в конце тоннеля, но это не точно.
Комментарии (652)
CodeViking
02.08.2017 22:47+11Может быть я не очень хороший программист, но JS я люблю. Однако считаю синдромом мечтать о том, чтобы всё было на JS.
taujavarob
07.08.2017 00:13-3Может быть я не очень хороший программист, но JS я люблю.
Многие любят JS — И это нормально.
Ненормально и странно, когда кто-то пишет — «Я люблю С++» или «Я без ума от PHP» или «Ничего нет лучше Python»
У уж если кто напишет — "Я люблю SQL" — его в дурку сразу определят.
Только про JavaScript вполне нормально сказать — "Я люблю JavaScript."
Про все остальные на свете языки можно только сказать — «Я использую ..., ибо мне это подходит(для решения моей задачи), да и мне платят за его использование.»
Имхо, конечно, имхо. (С)
TheShock
07.08.2017 02:32+5Почему ненормально? Я вот много лет писал на ЖС и сейчас пишу, мне нравится множество вещей на нем, но вот люблю C#, потому что мне нравятся эмоции, которые я испытываю, когда программирую на нем. Может вы ремесленник и относитесь к программированию исключительно как к монотонной скучной работе, но не все такие.
Я вот сейчас еще на Go много пишу, но совсем его не люблю, потому что очень неудобный язык. Так что да, под решение задачи подходит и даже больше C#, но люблю я все-равно C#, к JS я нейтрален, а Go не люблю. Что тут не так?
ik62
02.08.2017 22:50+15Когда такие гиганты как Facebook, Google, Microsoft и Twitter методично вливают многомиллионные потоки кровавых долларов в JavaScript инфраструктуру
А зачем же они это делают? Почему не вливают в кошерные языки?Strain
02.08.2017 23:04-5Могу предположить что использование JS фреймворков от фейсбука внутри самого фейсбука выглядит не так уж и страшно — из за высокого уровня культуры разработки, 100% покрытие юнит-тестами от и до. То есть они пишут инструмент для себя. Также возможно дело в средней цене за единицу времени js разработки / низком пороге входа — дешевле взять js джуна которых много, при необходимости обучить написанию тестов и дать ему таск чтобы он писал тесты и облазил в дебаггере код вдоль и поперёк пока всё не заработает как надо чем искать Scala / Java / Erlang / Elixir / Haskell / какого-то ещё разработчика.
ik62
02.08.2017 23:30+3Могу предположить что использование JS фреймворков от фейсбука внутри самого фейсбука выглядит не так уж и страшно — из за высокого уровня культуры разработки, 100% покрытие юнит-тестами от и до.
Ну по идее ничто не мешает делать то-же самое на бэкенде и со строгими языками, зачем-же cвязывться с js?
Также возможно дело в средней цене за единицу времени js разработки / низком пороге входа — дешевле взять js джуна которых много
Вот это может быть более похоже на правду.i360u
03.08.2017 09:29+9Хороший фронтендер на JS в среднем будет ничуть не дешевле аналогичных по уровню разработчиков на других популярных стеках. А зачастую и дороже. Дешевизна тут — большой миф, корни которого уходят к традиционно пренебрежительному отношению к "недопрограммистам" верстальшикам. Однако, в современных реалиях фронт часто оказывается гораздо сложнее бека.
Zenitchik
03.08.2017 13:52Вертальщик и фронтендер — две большие разницы. Я, вот, фронтеэндер, и систематически обращаюсь к верстальщикам, когда надо сотворить что-то этакое на CSS. У них уже своя наука.
i360u
03.08.2017 14:16Во первых, я о том и пишу, что фронтэндер — это вовсе не простой верстальщик. А во вторых — знать и любить CSS лучше любого верстальщика — очень не помешает любому фронтендеру. Это вообще один из показателей профессиональной зрелости, я бы не доверил писать фронт человеку, которому требуется помощь верстальщика.
bano-notit
03.08.2017 14:38А я бы доверил, потому что знать, почему
0 == '0'
для фронтэндера важнее, чем знать, почему для применения того, чтобы дети сfloat: left
не вылетали из родителя родителю нужно какие-то бордеры невидимые делать или ещё хлеще, почему при opacity !== 1 прекращает свою работу z-index.
Просто приведения типов можно объяснить, даже this можно знать на что будет ссылаться, а вот почему z-index перестал работать вы никогда не объясните, или почему нужен
position: relative
там, где есть какие-нибудь вещи. Там это аксиомы, а у нас хотя бы можно как-то объяснить и предсказать поведение, хотя в некоторых очень узких местах даже в js нельзя понять какого чёрта с приведением творится.i360u
03.08.2017 15:19+1В нашей команде (включая меня лично), по какой-то странной причине, у фронтендеров не имеется никаких проблем ни с первым ни со вторым. И все как-то объясняется и предсказывается. Более того, многие задачи решаются именно на уровне CSS наиболее эффективно. Но так не у всех, наверное, ок. Про профессиональную зрелость я писал.
bano-notit
03.08.2017 22:13Я понимаю, у меня тоже есть некоторый опыт составления красивых инпутов на :before и анимации всяких красивостей, просто потому что это быстрее и эффективнее, чем на чистом скрипте. Но вот именно сверстать лендинг без помощи верстальщика я не смогу.
i360u
04.08.2017 11:10Я говорю даже не о "красивостях" и анимациях. Даже простое знание селекторов и манипуляции с атрибутами могут избавить вас от огромного количества лишнего кода в JS и ненужной логики в компонентах. А это прямая зависимость с качеством кода и скоростью разработки. Остальное — также, так или иначе, позволяет оптимизировать рендер и делать многие задачи на более высоком уровне. Как следствие — CSS — становится органичной частью кода приложения, вы должны его полностью контролировать чтобы получать наиболее предсказуемый и качественный результат. А зная современные возможности веб-платформы верстать становится совсем не сложно и местами очень даже приятно. А использование какой-либо консистентной экосистемы UI-компонентов избавит вас от рутины. Но такой подход, конечно, более актуален в продуктовой разработке а не проектной (когда лендинги).
bano-notit
04.08.2017 11:53Скажем так, кнопочкам паддинги расставлять любой умеет, позиционировать оповещение с помощью
pos:fix
тоже все. А вот такие хаки как в этих самых лендингах, где оказывается, что браузер ведёт себя совершенно не логично, примеры такого поведения я привёл, вот это, по моему, я сам по себе как js разработчик знать не должен. Вот честно, мне легче настоящего верстальщика, который на лендингах собаку съел, спросить что там происходит и как это исправить, чем съедать свою собаку на лендингах. Я лучше мобиксовскую покушаю, это чуть перспективнее.
Но всё же, есть верстальщики профессионалы, люди которые знают все уловки и все баги браузера. Вот это прямо профессионалы. Я не считаю, что разработчик на js должен быть вот таким запиписечным профи в этом реально сложном деле, потому что там не получится понять, что за фигня происходит, пока ты не перелопатишь сам движок рендеринга. Лучше иметь одного профи знакомого, чем самому в этой чертовщине ломать ноги.i360u
04.08.2017 12:05Я не знаю с чем вы продолжаете спорить, оставайтесь при своем мнении. Я лично могу сверстать все что мне нужно, и многократно встречал ситуации, когда знание верстки мне было необходимо именно как разработчику, напрмер такие, когда от понимания особенностей рендера элементов в браузере сильно зависит структура компонентов.
bano-notit
04.08.2017 12:11Я вас поздравляю. Я не могу сверстать всё, что мне нужно без вопросов к профи, ответы на которые всё чаще сводятся "поставь родителю
position: relative
".
Может вы и правы, что неплохо было бы иметь такой скил в коробке, но целенаправленно выучивать эти грязнейшие с точки зрения логики хаки со всякими .clearfix, уж позвольте.punkkk
04.08.2017 13:46+1ответы на которые всё чаще сводятся «поставь родителю position: relative».
Как вы можете претендовать на фронтенд разработку? -_-bano-notit
04.08.2017 14:06Вот как-то вот так) Я же говорю, знакомый есть, который эти нелогичности объясняет как "ну вот так вот получилось, это нужно запомнить, чинится это вот так".
Zenitchik
04.08.2017 15:29+1претендовать на фронтенд разработку
Да запросто, если пишешь невизуальную часть фронтенда.
franzose
03.08.2017 23:44Мне всегда казалось, что фронтендер — человек, который занимается вёрсткой и пишет JS. В игровой индустрии, конечно, всё может быть иначе, но в основном-то это так.
Zenitchik
03.08.2017 23:48Во общем — Вы правы. Но когда пишешь толстый клиент, лучше чтобы за багами z-index-ов следил отдельный человек.
Zenitchik
03.08.2017 16:39Я не говорил, что не знаю CSS. Я говорил только что отдаю эту работу отдельному верстальщику. До этого два года работал без них (их не было), теперь с удовольствием освободился от необходимости подгонять внешний вид интерфейса под картинку нарисованную дизайнером — объясняю верстальщику, по какому принципу у меня элементам класс-неймы присвоены, и спокойно берусь за следующую задачу.
mclander
03.08.2017 20:09+3Блин. Пойду убьюсь.
Я могу верстать, но очень средненько и очень медленно. Если из рук проф дизайнера/верстака выходит красивое приложение, а мне этого не дано…
Приходится довольствоваться тем что из моих рук удобное и быстрое. Ну и более менее хорошо организованное.
И, что странно, при этом з/п среднего фронт-сеньора сильно выше з/п отличнийшего верстака.
А с тем что джуньоры на JS нафиг не нужны, а сеньоров рвут на лоскуты… знаком не понаслышке. На самом деле порог входа довольно таки дорогой. Только это не видно со стороны. Да, как автар статьи намекал, действительно из фронт-проекта сделать помойку легче лёгкого. Поэтому требуются очень люди с бэкграундом. Чтобы и подводные камни знали и по фен-шую работали.
AndreyRubankov
03.08.2017 15:54+3Верстальщики, как и JS девелоперы, это же подмножество фронтедщиков или нет?
т.к. Фронтэнд — это все, что связано с клиентской частью приложения, с отображением.
но если в общем это уже зависит от того, какие требования к фронтендщику предьявляют в какой-то конкретной компании, в более крупных — разделяют на 2 должности, в более мелких — это один человек.
odintree
04.08.2017 22:02я уже так давно не видел верстальщиков, если честно.
обычно из того, что видел это дело распиливают между собой дизайнер и чувак, который что-то пилит на angular/react/vue etc.
я и сам не люблю, да и скажу честно, плохо довольно работаю с этими CSS и HTML… но как-то никому в голову не приходит верстальщика брать еще. серьезно, думал они «вымерли» уже :Dbano-notit
04.08.2017 22:12Они не вымерли, и не вымрут, пока не появятся бесплатные нормальные генераторы лендингов, а они именно с этими 2 качествами не появятся никогда.
seniorcote
03.08.2017 00:03У них есть ряд причин так делать, но забота о разработчиках и их нервах в этот ряд не входит.
Hedgar2018
02.08.2017 22:53+5Тащить на backend интерпретируемые языки, а еще и без типизации — маразм. Только компилируемые и со строгой, желательно именной, типизацией (Golang или Rust, конечно же).
На клиенте же всё наоборот — нужна полная кроссплатформенность, а теперь и кроссдевайсность. Современные SPA фреймворки позволяют один такой bundle запустить на любом устройстве с экраном.
Но не на backend, ни в коем случае.
Пишу этот коммент только для того, чтобы выудить умные противоположные мысли из комментов к нему, если они будут.Hedgar2018
02.08.2017 23:12+6[Update]
В качестве JS только TypeScript.mclander
03.08.2017 20:14Трудности и радости секса в невесомости сильно преувеличены (с) А. Кларк (или А. Азимов, в общем кто-то из них)
За три месяца работы на TS был только один случай, когда типизация могла бы сэкономить мне время на отладку (бага поймалась в редакторе). В остальном мне больше нравится ES6, чем TS. Но правда у меня школа Perl, который позволяет ещё больше чем JS и спрашивает потом больно, неожиданно и на продакшене, если где что прощёлкал.raveclassic
03.08.2017 23:18+3Мы сейчас в процессе переезда нескольких библиотек на TS. Я уже сбился со счету сколько скрытых багов выявляется.
Iqorek
02.08.2017 23:24+8Говорят, что v8 компилирует js в нативный код, думаете врут?
knekrasov
03.08.2017 11:18А в конечном счете, все выполняется на вполне себе нативном ядре процессора с его микрокодом. Так что не врут.
Вопрос в другом, какие assumptions сделает компилятор, пока будет превращать JS в нативный код? Статическая типизация в этом смысле поможет избежать ложных assumptions и четче декларировать намерения. Но ее нет :-)
timon_aeg
03.08.2017 11:39На клиенте же всё наоборот — нужна полная кроссплатформенность, а теперь и кроссдевайсность.
Вы с css не путаете?
Есть всего 3,5 браузерных js движков, и все они более менее поддерживают стандарты.
oleg_gf
03.08.2017 12:27-10Языки с типизацией — унылое старьё. ))))
0xd34df00d
04.08.2017 04:02+5guai
03.08.2017 14:46-2На большом и мощном серваке иметь быстрые скомпиленные проги, а на дохленькой трубе обмазываться интерпретируемой динамикой или тратить скудные ресурсы на JIT не кажется ли вам странным?
Zenitchik
03.08.2017 16:48Сервер — один, труб — много. Нагрузка несоизмерима. Тем более, что сейчас каждая труба может баллистику звездолёта рассчитывать в реальном времени.
Free_ze
03.08.2017 19:42+3сейчас каждая труба может баллистику звездолёта рассчитывать в реальном времени
JS спешит на помощь избыткам мощности! (= Современные сайты жрут как не в себя и тормозят на десктопах, что уж о мобилках говорить.
speshuric
04.08.2017 09:06Эм… На бэкенде «интерпретируемые языки, а еще и без типизации» чуть ли не царствуют. Весь bash/shell/cmd такой. На них не пишут бизнес-логику? Ок, тогда SQL — он тоже по факту скорее интерпретирумый, с типизацией у него «всё сложно». Кстати большинство движков SQL однопоточные (внутри запроса параллельность может быть, но следующий запрос начнется только после окончания предыдущего). Если про веб, то PHP по меркам индустрии джититься стал чуть ли не вчера. ABAP, не к ночи будет помянут, тоже, хм, элегантен, как паравоз.
А ведь это языки на которых самое мясо бизнеса зачастую крутится. Тут скорее «Golang или Rust» пока в роли белых ворон.
[Я сторонник типизированных языков, если что]sumanai
04.08.2017 16:27Если про веб, то PHP по меркам индустрии джититься стал чуть ли не вчера.
Я что-то упустил, и в PHP впилили JIT? Вроде только в проекте, если речь про основную ветку.
aleXoid
02.08.2017 23:02+6Боль автора полностью обоснована. В последнее время я несколько увлёкся написанием ботов с MS Botframework, используя nodejs. Пока не перешёл полностью на Typescript — написание приложения больше 1000 строк, было настоящим мучением. Очень советую автору присмотреться к Typescript, как к костылю, который частично облегчает жизнь.
Strain
02.08.2017 23:17Благодарю! В современном мире увы каждый разработчик соприкасается с JS хочет он того или нет — больше или меньше, но это явление есть. Порой когда обсуждаю с друзьями-разработчиками какую-нибудь современную технологию кажется что находишься в клубе анонимных алкоголиков — то есть все знают что такое JS, почему он плох, но по разным причинам каждый становится замешан в этой экосистеме, иногда так и кажется что кто-то скажет
— Привет, меня зовут Олег, и я иногда пишу на JS. Нет, вы не подумайте в основном я Scala разработчик, но вот иногда приходится и в npm полазить и для grunt с webpack скрипты написать. Кстати, я не писал на JS уже 2 недели
— Давайте похлопаем Олегу
:)x67
04.08.2017 10:51меня зовут не Олег, я всеми силами пытался дистанцироваться от фронтенда, но несмотря на это мне уже приходилось писать на JS
Iqorek
02.08.2017 23:26+13Я бы не сказал, что Typescript костыль.
Hedgar2018
03.08.2017 00:01-1Хорошая вещь является костылём, если её предназначение — заставлять работать плохую вещь, когда её [почти] невозможно заменить.
Если бы браузеры понимали Typescript, он бы не был костылём.Iqorek
03.08.2017 00:18Компилятор Typescript написан на… Typescript. Если я ничего не путаю, можно прикрутить компилятор к страничке и генерировать код в браузере на лету, но так никто не делает, потому что зачем.
Hedgar2018
03.08.2017 00:29А как прикрутить к страничке что-либо, написанное на Typescript?
prostofilya
03.08.2017 07:58+6Что-то ребята на C++/C#/Java и тд тп всю жизнь компилируют и как-то не жалуются
Free_ze
03.08.2017 19:46+1Ребята компилируют в байткод, а то и в маш.коды, а не занимаются пустопорожними переливаниями между разными видами текстовых форматов.
Shifty_Fox
03.08.2017 21:02Ну про машинный код я еще могу понять логику, это непосредственный формат для процессора. И то, сначала код переводится в ассемблер, а уже потом в машинный код, так то.
В чем же разница подачи байт кода java машины или передачи javascript кода браузеру (мог бы он принимать javascript байт код напрямую, так бы и делали) мне сложно уловить.Free_ze
04.08.2017 12:41И то, сначала код переводится в ассемблер, а уже потом в машинный код
А до этого происходит токенизация, построение AST, линковка… Но это не имеет значения, на выходе из компилятора получаются уже готовые к исполнению модули.
В чем же разница подачи байт кода java машины или передачи javascript кода браузеру
Про Java об заклад биться не буду, но идеи там во многом аналогичны .NET CLI. Название как бы намекает: банальный текст против некоторого удобного для выполнения бинарного представления. Выгода здесь в оптимизациях, которые может провернуть компилятор (уровня модуля), удобной раскладки метаданных (стандартизированный формат, Карл! Поэтому байткод — кроссплатформенный, а в браузеры в 2к17 до сих пор шлют текстовые файлы). Да и просто байткод — это бинарное представление объектно-ориентированного ассемблера, использующий API виртуальной машины, а не сырой исходник, который еще необходимо распарсить, переварить во внутреннее представление (для конкретного движка), а потом как-то его исполнить.Shifty_Fox
04.08.2017 12:50+2Тогда это претензии конкретно к Chrome, IE, Firefox, Safari и другим браузерам.
Javascript не виноват, что разработчики браузеров не хотят принимать на запуск байткод.Free_ze
04.08.2017 13:00-1Если браузеры научатся понимать некий байткод, то дни JavaScript будут сочтены, ибо он перестанет быть безальтернативен на фронте.
AndreyRubankov
04.08.2017 13:24Был Flash, он принимал на вход байткод. Но его закопали.
Был Silverlight, он принимал байткод, — закопали.
Был JavaApplet… — закопали.
кто следущий WebAssembly?Free_ze
04.08.2017 13:37+1КМК, у этих платформ было две беды: проприетарность (и как следствие — уязвимость) и отсутствие стандартизации. Как мне известно, WebAssembly этих проблем не должен иметь.
AndreyRubankov
04.08.2017 13:54JavaApplet, как и вся джава – это стандарт, который может быть реализован разными компаниями. Но должен будет пройти сертификацию.
Flash… в целом он тоже стандартизирован и ближе к закату отдали в сообщество.
про Silverlight не могу сказать.
на счет уязвимостей. Уязвимости они не в технологии, они в имплементации, так что WebAssembly не защищен от уязвимостей.
У WebAssembly будет всего 2-3 реализации: под WebKit, под FF и под IE, т.е. от основных игроков рынка.
Но технология перспективная, так что нужно будет дождаться, когда она выйдет в свет в полной мере.Free_ze
04.08.2017 14:06JavaApplet, как и вся джава – это стандарт, который может быть реализован разными компаниями
Но не был де-факто (об этом ниже).
Flash… в целом он тоже стандартизирован и ближе к закату отдали в сообщество.
Когда он стал не нужен. Звон про уязвимости слышен до сих пор.
Уязвимости они не в технологии, они в имплементации, так что WebAssembly не защищен от уязвимостей.
Браузеры тоже не защищены от этого, но от них же никто не спешит отказываться, верно?) Я к тому, что чаще всего это были самостоятельные плагины, которыми рулила какая-то компания, которая же отвечала как за возможности, так и за безопасность. WebAssembly будет ограничена API браузера, из-за чего возможности Java-апллетов и Silverlight ей будут лишь сниться, зато у пользователей проблем будет меньше.
grossws
06.08.2017 17:47+1И то, сначала код переводится в ассемблер, а уже потом в машинный код, так то.
Зачем? В ассемблер переводят из внутреннего представления бэкенда компилятора только если пользователь слёзно попросил. А так кодогенерация идёт сразу в бинарное представление в объектном файле.
some_x
03.08.2017 07:40От этого браузер не начнёт понимать js, вы просто увеличите время загрузки)
andreysmind
03.08.2017 12:41Браузер переживет. А вот время разработки и отладки уменьшится.
some_x
03.08.2017 12:59+1С чего вдруг оно уменьшится?
Во первых начнёт глючить отладка, так как js появится из памяти, а не из файла. Из-за этого будет сложно ставить брекпойнты, например.
Во вторых, какая разница до загрузки ts будут компилироваться или после, всё равно время на компиляцию будет затрачено.
В третьих вывод компилятора удобнее читать в ide, чем в консоли браузера.
BuccapuoH
02.08.2017 23:06+14Согласен со многими фактами, приведенными в статье, но позвольте несколько замечаний и вопросов (я JS разработчик).
1. const — слышу о нём почти отовсюду. Но вот незадача — почему все думают что он должен работать точно так же как в С/С++/<вставьте любимый язык>. Я не спорю, реализация у него не лучшая, но это специфичная для языка конструкция, коротая имеет довольно простую функцию.
2. this — подобно const, крайне непонятая многими особенность языка. И опять же — использовать её необязательно.
3. Отсутствие нормальных классов/ООП. Недостаток только для людей, которые привыкли к ООП. Но соглашусь, те попытки создать ООП в JS, которые были — очень далеки от привычных многим концепций в Java/C/C++/C#/<добавьте свой язык>.
4. «Многомиллионные инвестиции кровавых денег от больших корпораций». Вы так говорите, как будто это что-то плохое. Ни один язык не станет популярным на голом энтузиазме его последователей. Нужны деньги, нужна реклама, нужна раскрутка. Как, по-вашему, работодатели узнают о языке/библиотеке/фреймворке, если он на слуху только в технических кругах?
В общем и целом, я к тому, что у всех языков есть недостатки и достоинства. У всех есть свои ниши и свои задачи. Языки — всего лишь инструменты.
С тем же NodeJS, многие его хаят за то, что он посягает на святая-святых — backend. Но я думаю, что если JS не подходит для backend и он настолько плох — разработчики будут жаловаться. Жалобы поднимут дискуссии, появятся решения, новые версии, патчи и исправления. И если этого будет недостаточно, то люди перестанут этим языком пользоваться. И он уйдёт из этой ниши. На его место прийдет другой и попытается привлечь к себе внимание, чтобы начать дискуссию. Потому как дискуссия и обсуждение — главные способы сделать язык лучше.
Java тоже не сразу стала удобной. Её тоже не все готовят правильно, есть жуткий код, есть хороший.
С радостью выслушаю мнения насчет JS и его представления на уровне backend.
sfi0zy
02.08.2017 23:47+9this — подобно const, крайне непонятая многими особенность языка
Но стоит один раз понять — и все, больше никогда этот вопрос не доставит проблем. А со стрелочными функциями использовать this стало очень приятно.
Но соглашусь, те попытки создать ООП в JS, которые были — очень далеки от привычных многим концепций в Java/C/C++/C#/
Да нет, в ES6 классы сделали вполне нормальные. Да, в них может не хватать чего-то, к чему привыкли приходящие из других языков, но это уже не та жесть на прототипах, которую писали 10 лет назад.
Жалобы поднимут дискуссии, появятся решения, новые версии, патчи и исправления.
В последние годы JS вообще очень сильно развивается, столько всего появилось… Автор поста говорит, что в JS нет единой системы в отношении модулей, работы с асинхронностями, и.т.д. но ведь это по сути является следствием того, что язык развивается, люди пробуют разное и пытаются выбрать лучшее. Просто здесь (как и в том же С++, кстати) не выпиливаются многие старые решения, они просто используются все меньше и меньше.BuccapuoH
03.08.2017 00:46+2Полностью согласен. Очень многие вещи усваиваются с полпинка. Как вы сказали — это уже не та жесть, которую писали 10 лет назад.
ES6 для меня был как глоток свежего воздуха. Последующие стандарты только улучшают ситуацию.
Я думаю, что люди из других языков и парадигм нужны в JS сообществе. Способность посмотреть на вещи под другим углом может привнести (и зачастую, привносит) хорошие идеи.
quwy
03.08.2017 00:17-3Но я думаю, что если JS не подходит для backend и он настолько плох — разработчики будут жаловаться
С чего бы это? Его в бекенд отнюдь не java/c#-гуру тащат, а вчерашние формошлепы, которые больше ничего другого не знают и знать не желают. Вот они конечно же всем довольны, а так как таких с каждым днем все больше становится, то никуда эта зараза уже не денется. Можно хоронить нормальный бэкенд, его уже не спасти.
О чем речь, эсли эта хипстота свой жабаскрипт даже на контроллеры тащит? Типичный представитель, которому лень учиться и поэтому он все хочет писать на любимом js.
Я уже молчу про десктоп, который благодаря гигантской производительности сегодня готов простить пользователю даже «электрон».Shifty_Fox
03.08.2017 02:03+9Вы знаете, после бекенда на lua/java/c++ бэкенд на node js (es7-8) сплошное удовольствие.
erlyvideo
03.08.2017 11:00-7это первые 20 строк кода, просветление наступит позже. А луа конечно сравнивать нельзя: кошмар похлеще js
Shifty_Fox
03.08.2017 17:10+3У меня сильно больше 20 строк кода, и даже больше 2000 строк, и все еще сплошное удовольствие
Если конечно быть в теме, использовать es7-8, не делать лапшу, а писать псевдосинхронный код, ну то есть понимать инструмент и правильно его использовать.
Непосредственно nginx использует lua, на этой базе построен openresty. На этой базе успешно строят производительные игровые серверы.
Lua Jit по производительности практически на одном порядке с нативным C++ кодом (ну конечно мета магия и динамическая типизация делают свое дело, но и применяя виртуальное наследование и динамический диспатчинг с хеш таблицами на C++ будет такой же результат).
Что касается парадигмы однопоточной работы. Это именно парадигма, а не какой-то там недостаток, как утверждали в ветке выше. Во первых, как в Lua, так и в JS на node нет никакой проблемы сделать мультитреды прямо из Lua\JS. И там и там прекрасно работают C++ расширения. Но смысл парадигмы в том, чтобы управляющий поток был один. Это шардинг из коробки, он принуждает вас писать приложение так, чтобы потом шардить его на самом первом уровне.
Это возможность, в конце концов, установить ряд глобальных состояний, и быть уверенным, что другой поток его не потеряет, потому что поток один. Второй поток — второе состояние, отдельное и независимое. Для общих данных же можно использовать как расширение с мультипоточностью, так и шардинг, оставаясь в пределах одного потока на процесс.Free_ze
03.08.2017 19:50Lua Jit по производительности практически на одном порядке с нативным C++ кодом (ну конечно мета магия и динамическая типизация делают свое дело, но и применяя виртуальное наследование и динамический диспатчинг с хеш таблицами на C++ будет такой же результат).
Самый быстрый Lua хуже не более, чем на порядок самого тормозного С++?) Маркетинг такой маркетинг.Strain
03.08.2017 19:55LuaJIT — один из лучших однопоточных компиляторов, смотрите пример. Но это не меняет того факта что однопоточный рантайм для высоконагруженного серверного приложения — это просто не серьёзно.
Shifty_Fox
03.08.2017 20:30+2Повторюсь, включить многопоточный рантайм не проблема как в серверном Lua так и в Javascript. Но его там не включают намеренно. Полагаете, из глупости и несерьезности?
izzholtik
04.08.2017 09:01-2Полагаю, да. Разработчики языка не осилили сделать нормальную многопоточность, следом не осилили её разработчики фреймворков, и теперь мы имеем то, что имеем.
Shifty_Fox
04.08.2017 12:55+1Я осиливал модель с сериализацией объектов и передачей между потоков. И классическую модель, когда объект просто общий на два потока. Многие разработчики расширений под Lua и JS осиливали обе этих моделей. Их решения известны, и даже используются в ряде проектов. Но они используются тогда, и только тогда, когда разработчик знает зачем ему нужна именно многопоточность в одном процессе с общими данными. В остальных случаях он масштабирует сразу процессы, и это масштабирование можно разнести не только на ядра, но и на разные серверы.
Многопоточность с общими данными — это как бы очень специфический кейс, нужный в 0.1% задач. В остальных случаях нам важнее иметь другую многопоточность — на уровне IO, а код должен синхронно обрабатывать таски, и параллелиться по процессам.
Strain
04.08.2017 09:04+1И где же эта волшебная кнопка включения? Пример? Большинство кодовой базы js / lua / python просто перестанет работать правильно в многопоточном рантайме.
Shifty_Fox
04.08.2017 13:01Ну, свою волшебную кнопку я дать не могу — я писал свой фреймворк для личных задач, и там кодовая база работала как в одном так и в нескольких потоках.
Не возьмусь утверждать что включение таких расширений совсем не отразится на стандартных функциях, все таки либо вы изначально пишите однопоточный псевдосинхронный код, либо сразу учитываете, или подводите кодовую базу под многопоточность, это абсолютно нормально.
Под Lua я встречал:
http://lualanes.github.io/lanes/
Под JS я глубоко не копал этот вопрос, принцип у JS и Lua в плане C++ биндингов одинаковый, и мета методы схожие, я знаю что в JS можно провернуть похожий трюк, и встречал npm пакеты утверждающие что они этот трюк проворачивают. Возможно, готовой кнопки там нет, но ее можно сделать.
Shifty_Fox
03.08.2017 20:35Ну никто не спорит, что быстрый C\C++ код без динамических типизаций будет рвать любой язык с jit и динамической типизацией. Но это просто два уровня подхода.
Ну и в lua и node можно делать C++ расширения, если в каком-то месте нужно решить проблему производительности.
Другое дело что вам возможно просто не нравится концепция «скриптовый язык сверху, C++ снизу», а больше нравится концепт «не туда и не сюда, но все еще можно сделать снизу C++», как в Java\C#Free_ze
04.08.2017 12:50+1в lua и node можно делать C++ расширения, если в каком-то месте нужно решить проблему производительности.
Node.js так воспевался возможностью писать приложения на одном языке, а тут архитектурные костыли в виде расширений на нативных языках.
Другое дело что вам возможно просто не нравится концепция «скриптовый язык сверху, C++ снизу», а больше нравится концепт «не туда и не сюда, но все еще можно сделать снизу C++», как в Java\C#
«не туда и не сюда, но все еще можно сделать снизу C++» — я бы назвал это адекватным балансом между производительностью, удобством поддержки ПО и производительностью.
Лично мне не нравится дизайн JavaScript, поэтому и удивляет рьяное желание засовывать его везде, начиная с бэкенда и заканчивая микроконтроллерами.Shifty_Fox
04.08.2017 13:39Я не воспеваю идею писать все на одном языке :)
Я воспеваю идею писать 90% приложения на одном языке, а 10% — на голом Си.
«не туда и не сюда, но все еще можно сделать снизу C++» — я бы назвал это адекватным балансом между производительностью, удобством поддержки ПО и производительностью.
Это же вопрос вкуса. Мне нравится, когда сверху язык совсем совсем динамический, легкий, немногословный (камень в java, но без претензий), а все что требует оптимизации, делать сразу на самом низком уровне в Си.
Вам нравится, когда сразу баланс.
Могу пояснить, откуда вообще растут корни такого подхода.
Как правило, нужно сделать 5-10 прототипов разной направленности, протестить на пользователей, понять что развивать а что нет, а потом уже делать полноценный продакшн, но не переписывать с нуля, а вертикально развивать существующий. Для этого связка JS + C подходит отлично.
Если бы мне дали энтерпрайз банкинг я бы врят-ли писал его на JS, это не его задача.Free_ze
04.08.2017 13:50Как правило, нужно сделать 5-10 прототипов разной направленности, протестить на пользователей, понять что развивать а что нет, а потом уже делать полноценный продакшн, но не переписывать с нуля, а вертикально развивать существующий. Для этого связка JS + C подходит отлично.
Как это потом поддерживать — вопрос (мало того, что динамический язык, так еще и половина бизнес-логики ныряет в другой язык через всякие прослойки). Ну вкусовщина, ОК.Shifty_Fox
04.08.2017 19:36Мне хорошо и легко поддерживать, честно.
Я выбирал этот концепт не из позиции сначала легко а потом будет выкручиваться, а с позиции легко на всех этапах.
Но так то да, вкусовщина.grossws
06.08.2017 18:07А есть примеры кодовой базы среднего (100k SLOC) и выше среднего (1M SLOC) размеров на JS с рассказами о поддержке такого?
Shifty_Fox
07.08.2017 06:44Могу скопировать тройку классов из клиент-серверной игры в github gist
Классы с сервера, используют C++ биндинги, синхронизируются с клиентом.
то есть весь C++ код дублируется js кодом, чтобы каждый кадр был синхронизирован, и обновлялся с сервера только при изменении ключевых параметров на сервере (нажали кнопку, пришел новый вектор движения, нажали на дверь, пришло событие открытие двери). Этот код моего проекта, я могу его публиковать, но не стану публиковать весь проект.
Код не претендует на идеальный, но он и не плохой, где-то хорошо, где-то не очень.
https://gist.github.com/dmitriy-lodyanov/d0559323986a6faaf78b93e272690766
https://gist.github.com/dmitriy-lodyanov/f17f7613197b75e2109d075e65b42f89
https://gist.github.com/dmitriy-lodyanov/d59b3301d6247fcc3ec5c52895820dc6
Врят ли пара классов даст представление о целом проекте. Это простая mmorpg в стиле dark souls, с видом сверху.Shifty_Fox
07.08.2017 06:49Еще добавлю gist основного update(dt) сервера на C++. Он не дублируется на клиенте за ненадобностью, на клиент приходят постфактум физика и события, то есть на клиенте столкновения не обсчитываются.
https://gist.github.com/dmitriy-lodyanov/38cd8e42c7bef4889cdd752fc3459166Shifty_Fox
07.08.2017 06:53А поддержка всего этого…
Наверное также, как вы поддерживаете свои проекты. Просто держите в голове архитектуру, знаете ключевые точки, знаете где нужно добавлять объекты и расширения для новых функций. Я использую классическую модель игровых циклов, когда есть дерево объектов, каждый кадр по ним проходит обновление, во время событий срабатывают триггеры. Сервер работает на 30 fps, клиент на 60 fps. Благодаря математически корректным формулам равноускоренного движения, при разных fps на сервере и клиенте объекты все равно двигаются синхронно независимо от dt.
0xd34df00d
04.08.2017 04:03+1Не троллинга ради, но любопытства для: откуда я могу начать получать удовольствие от node.js по сравнению с C++?
greendimka
04.08.2017 10:22-2JS: Пишите — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите — вдруг заработало. Вот тут вы и получаете удовольствие.
bano-notit
04.08.2017 11:59Позвольте, это не так. Там скорее так: Пишите — не работает. Пишите — не работает. Пишите — о, что-то заработало! Пишите — о, ещё что-то подтянулось! Пишите — ну а теперь вообще всё тип топ.
Удовольствие приходит начиная с 3 шага.raveclassic
04.08.2017 12:27-1На самом деле, удовольствие приходит с TS :)
bano-notit
04.08.2017 12:37+1Не соглашусь, тогда уж довайте на cloujer писать сразу, зачем нам сам js то?
raveclassic
04.08.2017 12:39-1Ну кложа на любителя. А зачем js, когда есть ts — сам не знаю.
bano-notit
04.08.2017 12:40+3Зачем ts, когда есть js, вот это я реально не понимаю.
raveclassic
04.08.2017 12:42-1Тут полно комментов зачем. Хотя бы чтобы решить большинство описанных проблем на этапе компиляции.
bano-notit
04.08.2017 12:47-1Позвольте, проблемы описанные тут занесены людьми, которые изначально писали на каких-нибудь плюсах да шурупах, и пришли сюда устраивать тут свои законы. В js как писали отлично без тайпскриптов так и пишут и будут писать, потому что ретурн забыть поставить — нерадивость программиста. Решения проблемы "что же возвращает функция" — jsdoc с поддержкой в ide, которая кстати работает быстрее любых flow и тем более ts, который ещё компилировать надо. Так что нет, проблем нету, они были завезены из "забугорья", и от туда же завозят решения.
raveclassic
04.08.2017 12:49Давайте просто не будем об этом. Не охота опять начинать холивар на тему ts vs jsdoc.
pnovikov
04.08.2017 12:55+1Да, давайте держать типы в голове или в документации. А верифицировать их не компилятором, а пристальным взглядом. Правильно. Зачем пользоваться технологиями, когда есть человеческий мозг? :)
bano-notit
04.08.2017 12:58-2Позвольте, в голое никто никогда ничего не держит, у нас есть прекраснейшие ide, которые не только типы из jsdoc'ов могут выдрать, но и свойства подсказать. Так зачем нам ещё куча компиляторов, если у нас есть уже инструмент, который и так парсит всё это дело в реальном времени и следит за всем адом преобразований, происходящем в коде?
raveclassic
04.08.2017 13:02+2А для CI вы тоже IDE как-то разворачивать собрались?
bano-notit
04.08.2017 13:09А зачем ci компиляторы из одного языка в другой, если задача постоянной интеграции — выкатывать в автоматическом режиме продукт на продакшн, с проведением перед этим тестов? Компилирование там как раз такие никаких плюсов не даст, оно по вашим же заверениям помогает разработчику проверить сходятся ли типы. На момент тестирования уже глубоко пофигу, тестируется то всё равно готовый js, в котором уже нету ваших интерфейсов да всего остального.
raveclassic
04.08.2017 13:16+2Во-первых CI — не CD.
Во-вторых, проверка "сходятся ли типы" является частью тестов.
В третьих, как раз-таки не пофигу, так как, забивая на типы на CI, вы делаете шаг назад и тестируете подверженный багам код. Или вы из тех, кто пишет тесты на типы входных аргументов?
bano-notit
04.08.2017 13:24Я пишу тесты на работоспособность, а не на входные типы, если оно не работает при всех возможных ситуациях — нужно понимать почему не работает, и это всё очень часто происходит не из-за не соответствия типа, а из-за того, что просто перепутал местами члены выражения в операции деления или просто не то свойство взял, типы там не влияют, потому что в доках указано, что принимается, а что отдаётся.
pnovikov
04.08.2017 13:44Я вот как раз написал Reinforced.Typings, держа в голове проблему, которую решает ваша дока. Если у вас есть клиент к REST-сервису, то если у того внезапно поменяется контракт и вместо объекта
{ Name: '...', Age: '...' }
ВНЕЗАПНО владельцы сервера решат отдавать{ FirstName: '...', BirthDate: '...' }
— то используя TypeScript и генерацию тайпингов вы узнаете об этом еще до того как запустите приложение. В случае с голым JS — такой баг скорее всего обнаружат таргет-юзеры.raveclassic
04.08.2017 14:49А мы swagger-codegen используем, кода генерим TS с REST'а
pnovikov
04.08.2017 15:12А мы прямо из MVC-контроллеров. Не хочется ради такой мелочи тащить swagger в проект
raveclassic
04.08.2017 15:35Ну у нас джависты и так сваггер-спеку отдают. А тут просто звезды сошлись, чего б не генерить с нее ts.
0xd34df00d
04.08.2017 19:30Как часто у вас ломаются тесты в процессе разработки? Да ладно там, лучше скажите, как часто у вас ломаются тесты в процессе рефакторинга?
Мне хорошо, как только код собрался, в 99.5% случаев тесты сразу зелёные. Просто тайпчекер сам по себе выступает этаким тестировщиком, и зачем мне добровольно брать на себя его работу, мне не очень понятно.bano-notit
04.08.2017 21:06Ломка тестов при изменении кода — достаточно частое явление. А если уж у вас 99.5% — да вы просто бог, мифическое существо. Ещё скажите, что люди, которые это тестируют вам обратно не отдают на доработку в 99%, если скажите, то я вам прямо поклонюсь.
0xd34df00d
04.08.2017 21:13При рефакторинге, не при всяком изменении. При рефакторинге редко меняется используемый алгоритм или прочая логика кода.
На плюсах, скажем, когда пишу, при рефакторинге тесты ломаются у меня сильно чаще. А вот на хаскеле… :)bano-notit
04.08.2017 21:17При рефакторинге не должно конечно же, но всё же когда переосмысливаешь подход, а именно это при рефакторинге обычно должно делаться, а не просто разнесение куска вычислений и сравнений в переменные, должна чуть чуть улучшаться и логика, и соответственно не должно поведение, вот тесты и смотрят, чтобы поведение оставалось ожидаемым. А уже получилось ли сразу оставить логику полностью правильной, или в каком-то месте что-то не учёл — вот это уже тебе тесты и скажут.
Прошу прощения, на плюсах только хеловорлдами баловался да чужими лабораторками, хаскеля вообще в глаза не видовал.
0xd34df00d
04.08.2017 19:28+4IDE способно лишь проверить, является ли код в известной мере консистентным с точки зрения типов, но не более.
Во-первых, у меня нет способа верифицировать модель кода, скажем, расставив в некоторых частях кода аннотации типов и убедившись, что всё им соответствует.
Во-вторых, есть ли у меня способ выразить «это Int, и это Int, но это два разные по смыслу Int'а, поэтому если я вдруг начну сравнивать один с другим или вообще использовать их в одном выражении, пни меня, пожалуйста»?bano-notit
04.08.2017 21:10Flow пробовали? Он может понять достаточно простой код, если ему расставить в нескольких местах аннотации, но к сожалению с тем же redux и connect из react-redux он уже не справляется, ему нужно в каждом месте указывать, какие типы данных ожидаются на вход колбеков.
2 по смыслу разных инта… Интересно, а в ts вы тоже каждому инту свой тип даёте, или вы всё же под 2 разных по смыслу инта делаете 2 разных по смыслу типа, которые расширяют инт, ну или не расширяют, а как-то по другому просто копируют его "интерфейс", но имеют отдельное имя типа?
0xd34df00d
04.08.2017 21:19+1Flow пробовали?
Не пробовал, я вообще не фронтендщик, мне хватает чужих питонячьих скриптов, которые иногда приходится читать.
2 по смыслу разных инта… Интересно, а в ts вы тоже каждому инту свой тип даёте, или вы всё же под 2 разных по смыслу инта делаете 2 разных по смыслу типа, которые расширяют инт, ну или не расширяют, а как-то по другому просто копируют его «интерфейс», но имеют отдельное имя типа?
Я в ts по аналогичным причинам ничего не делаю, а в более других языках у меня есть newtype, скажем.bano-notit
04.08.2017 21:26Я всегда страдал косноязычием, я как раз и говорил, что для разных по смыслу инта вы определите 2 разных по названию типа, чтобы компилятор вас потом по рукам бил, если ожидалось одно, а пришло другое, так вот, в jsdoc тоже есть такая конструкция как typedef, и ide будет несколько недоумевать, когда вы ей подсунете вместо функции похожей по параметрам на middleware функцию, которая ожидает 1 параметр — число и вообще возводит это число в квадрат. Но flow вообще пошлёт лесом при таких изысках, соответственно и ts должен послать.
0xd34df00d
06.08.2017 01:17Если я правильно понял ваш исходный тезис, то в нём говорилось о ненужности компиляторов, тайпчекеров и прочих подобных инструментов, ведь есть же IDE. Flow и TS как-то уже не очень вписываются в эту парадигму.
AxeLWeaver
04.08.2017 17:21+1А если я пишу и у меня заработало с 1го раза? Я сломал систему?)))
bano-notit
04.08.2017 21:02Если у вас получается с первого раза, значит вы правильно следовали мануалу "Get Started" того фреймворка, который выбрали для работы) Дальше уже нужно будет делать уже что-то, что требует отхода от этого мануала, и тогда уже начинается именно тот цикл)
AxeLWeaver
04.08.2017 21:05Спасибо, фреймворками не пользовался, лишь библиотечкой jQuery, просто вздумалось написать «Сапёра» на JavaScript, что-то похожее получилось, но всё время хочется «непоправимо улучшить», написать на чистом JS и как можно ближе к оригиналу.
bano-notit
04.08.2017 21:13jq — отдельная песня. Сам по себе неплохая идея синглтона в контексте сложности обычного интерфейса dom, но сами подумайте, это просто обвес, который добавляет только удобство и ни капельки функционала неповторимого и прибавки к эффективности. Поэтому я последнее время стараюсь незаметно подменить jq на zepto, чем и Вам советую побаловаться. Ибо быстрее, легче, а интерфейс тот же.
AndreyRubankov
11.08.2017 21:39Главное потом вдруг не выполнить npm i, который вам сломает проект обновлением зависимостей :-(
BuccapuoH
03.08.2017 11:29+10Не гребите всех под одну гребёнку. Фармошлёпов хватает во всех языках. Сам факт появления NodeJS (как и других библиотек/движков/языков) недвузначно намекает, что не всем нравится java/C# на бэкенде. Называть людей фармошлёпами только потому что они решили попробовать что-то новое, ИМХО, несправедливо.
И опять же — никто не забирает хлеб у Java/C# — в них тоже денег вливают неплохо. За ними тоже не кто-попало стоит. У всех свои ниши и NodeJS — не серебряная пуля, как, впрочем, и Java/C#.
AndreyRubankov
03.08.2017 09:07+51. const — слышу о нём почти отовсюду. Но вот незадача — почему все думают что он должен работать точно так же как в С/С++/<вставьте любимый язык>.
Вот только const в ES2015 – работает точно так же как в C/C++/C#/Java: он запрещает изменять ссылку, но не запрещает изменять значения внутри объекта. Изменяемые объекты и коллекции будут работать одинаково – будут изменяться даже если их объявить с const (в java const назвали final, чтобы не давать ожидания, что весь объект будет неизменяемым).
С тем же NodeJS, многие его хаят за то, что он посягает на святая-святых — backend.
На самом деле NodeJs вполне подходит для некоторых задач WEB бекенда.
Тяжелые расчеты или преобразования он сделать не может в силу единого event loop и отсутствия многопоточности, но получить данные из базы или перенаправить запрос куда-то в другой сервис (то, что сейчас многие бекенды делают) – с этой задачей NodeJs справится без проблем. Единственное чего нехватает – flow types, чтобы уменьшить количество тупых ошибок.
irbis_al
02.08.2017 23:17+4А Автор Топика например делал soap клиент на java?(Про сервер-soap я вообще молчу)
Пусть попробует… а в node
var soap = require('soap'); var url = 'http://localhost/wsdl?wsdl'; var args = {name: 'Имя'}; soap.createClient(url, function(err, client) { client.SayHello(args, function(err, result) { console.log(result); }); });
Причём пусть изменит метод сервера… и потом помучается с java… а тут просто client.SayHellonew надо поменять.
А сокеты… передать файл по сокету… попробуйте кодом на java и на node…
В ява…
пока есть данные читаем поток сокета пишем в выходной поток.
в ноде
socket.on('data',(data)=>{console.log(data)});
А http client? а http сервер… Я Вам за 18 секунд подниму http сервер на node.
На node код в 40 раз короче…
И при этом(в моём опыте даже быстрее) не медленее.(Как они этого добиваются в одном потоке вообще непонятная магия)
Я сам пишу на java и на node… и есть с чем сравнивать ,-ноде это простота кода и ёмкость… сосредотачиваюсь просто на решении., а не на обрастании синтаксических лексем.Strain
03.08.2017 00:43+1А Автор Топика например делал soap клиент на java?(Про сервер-soap я вообще молчу)
Справедливости ради нужно сказать что мой главный промышленный язык это Erlang, с 2013 года Elixir. Формально это языки со слабыми типами, как и JS ( правда без неявных преобразований ) поэтому формально ответ — нет. На Erlang / Elixir код будет тоже более компактный по сравнению с Java. Но опять возвращаясь к слабым типам — в экосистеме Erlang / Elixir есть чудесные инструменты для статического анализа такие как Dialyzer и Xref. При правильном стиле написания кода ( тут ничего сложного нет ) эти инструменты выводят алгебраические типы для 100% функций и выражений в исходниках, буквально для каждой строчки и каждой буквы кода. То есть потенциальные проблемы с типами и просто опечатки видны ещё до запуска программы ( эти утилиты анализируют скомпилированный байткод ). В отсутствии подобных инструментов заключается один из главных минусов JS экосистемы.Grox
03.08.2017 02:00+4TypeScript решает это для JS. Через поддержку в IDE, ещё до компиляции. Вопрос с типами снят?
Shifty_Fox
03.08.2017 17:13Я вам еще помогу, а то по тредам либо JS, либо TS.
Есть еще замечательный Flow, у которого есть режим совместимости синтаксиса. Он анализирует JS код и дает статические проверки. Можно не покидая JS решить эту проблему.Strain
03.08.2017 17:51TS — всё-таки это другой язык, не JavaScript. Да и Flow предполагает написания нотации типов для функций — необходимо их явно указывать. Это лучше чем ничего, согласен. Но есть реально классные компиляторы которые позволяют выводить типы для всех функций в программе без единой нотации типа. Вот пример простой программы на PureScript ( диалект Haskell компилируемый в JavaScript ), вот этот же код в работе. Код полностью типизированный и безопасный. Ни единой нотации типа в коде нет. Вот такая магия. В 2017 году многие компиляторы так умеют. Ещё раз спасибо за совет!
VioletGiraffe
03.08.2017 08:13+2А можно поинтересоваться, где это в реальной жизни используется Erlang (который я всегда считал академическим языком, как и большинство функциональных, кроме, может быть, Lisp)?
Strain
03.08.2017 08:43Тут тоже не обошлось без корпораций конечно. Язык был создан компанией Ericsson в 1986 году, фирма продолжает и до сих пор вливать в него евро, недавно был релиз 20й версии. Изначально Erlang был создан под одну единственную задачу — написание ПО для маршрутизаторов ( этого же самого Ericsson ), в связи с этим там изначально отсутствовали некоторые казалось бы необходимые типы данных такие как например строки или maps, не было нормальных кастомных типов данных. Но со временем Erlang стал языком общего назначения на котором пишется почти всё что угодно. Используется по-прежнему в основном в телекоммуникациях / телефонии, очень хорош для высоконагруженных систем из-за простых и надёжных средств параллелизации ( которые кстати были ещё в первых версиях OTP середины 80х ). С приходом Elixir, платформа стала действительно популярной и на ней пишется буквально всё. Особый вклад в популяризацию Erlang / Elixir внёс фреймворк Phoenix — это новая рельса, без преувеличений.
mayorovp
03.08.2017 09:27+2На Erlang написан RabbitMQ, к примеру. Еще на нем был написан популярный XMPP-сервер, но название не помню.
farcaller
03.08.2017 10:21на нем написан бекенд ныне крайне популярного в некоторых кругах чата Discord.
bano-notit
03.08.2017 13:14Да вроде на эрланге и у вотсапа бек написан...
kaljan
03.08.2017 14:56Вотсап это старый добрый xmpp под капотом
bano-notit
03.08.2017 22:21Изначально, но потом они его посадили на свои бустеры с переписью части самого ejabberd. Короче они неплохо заморочились, поэтому фб наверное таки деньги за это отвалил...
kaljan
03.08.2017 22:37+2а я думал фейсбук отвалил такие деньги за количество людей которые пользуются ватсапом)
bano-notit
03.08.2017 22:41Ради одних только людей у него есть свой меседжер и вообще-то говоря нехилое количество клиентов самой соц сети.
irbis_al
03.08.2017 08:52+2Вы сказали
>>Справедливости ради нужно сказать что мой главный промышленный язык это Erlang, с 2013 года Elixir.
Вот я не знаю… что тут добавить… чего тогда анализируете java против node… Вот я пишу глубоко на том и на том… и могу позволить себе небольшой анализ.(Там вверху я написал где node рвёт java как тузик грелку… но у меня есть и случаи где java пользовать предпочтительнее… просто недостатки языка это продолжение достоинст)
Noa69
03.08.2017 11:55+4Я Вам за 18 секунд подниму http сервер на node.
А я вам за 1,8 секунды его положу, например.Coffin
03.08.2017 17:18+1рецепт в студию :)
copist
03.08.2017 20:59$ npm install -g node-static # install dependency
$ static -p 8000
(источник: Big list of http static server one-liners)bano-notit
03.08.2017 22:22-1Можно всё же вместо
install
использовать простоi
так же как и-g
вместо--global
.
copist
03.08.2017 21:06+1положить
$ npm install -g loadtest
$ loadtest [-n requests] [-c concurrency] [-k] URL
Apx
03.08.2017 20:20Why not python? Или рубя в который можно одной строчкой всё наговнякать?
Не стоит забывать для чего изначально делался язык и какие тогда были ограничения
zirix
03.08.2017 23:23+1А http client?
на java:
String text = IOUtils.toString(new URL("http://...."), "UTF-8");
(import org.apache.commons.io;)
а http сервер
@Controller @EnableAutoConfiguration public class SampleController { @RequestMapping("/") @ResponseBody String home() { return "Hello World!"; } public static void main(String[] args) throws Exception { SpringApplication.run(SampleController.class, args); } }
irbis_al
03.08.2017 23:38-4Да??? Прям так… Пробую скомпилить и запустить… ах блин… мне же надо либо мавен либо gradle файл сделать… так… почитаем как его делать… Ой что-то я с синтаксисом мавена не разобрался/накосячмл… сейчас погуглю.
А в node(для линукса)
yum install node(Вот даже ноду установлю для Вас) mkdir myhttp npm install express node mydir/bin/www
Можете сами попробовать
Я теперь soap клиент сделайте...websocket сделайте… файл по сокету передайте…
И сделайте это там и там… как я в соё время сделал… и офигеете как всё просто…
А древние говорили…
Упрощать сложно… а вот усложнять легко.
Я писал выше, что пишу глубоко на ноде и ява… и есть с чем сравнить… а Вы видимо только на яве.Ноде лаконичнее… легче читается… не задумываешься об всяческих лексемах.vintage
04.08.2017 00:41websocket сделайте… файл по сокету передайте…
Не Ява, конечно, но другой, не менее статически типизированный язык:
import vibe.d; this() { "wss://websockets.example.com/".URL.connectWebSocket.send( "./data.bin".readFile ); }
Сможете на ноде так же просто и лаконично?
zirix
04.08.2017 04:34websocket сделайте… файл по сокету передайте…
Так должно сработать:
@ClientEndpoint public class CustomClientEndpoint @OnOpen public void onOpen (Session session) { ByteBuffer byteBuffer = ByteBuffer.allocate(1000); try (FileInputStream file = new FileInputStream("/path/to/file")) { byteBuffer.put(IOUtils.toByteArray(file)); } byteBuffer.flip(); session.getBasicRemote().sendBinary(byteBuffer); } } WebSocketContainer container = ContainerProvider.getWebSocketContainer(); container.connectToServer(CustomClientEndpoint.class, new URI("ws://localhost:8080/path"));
zirix
04.08.2017 05:06забыл maven:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency> </dependencies>
irbis_al
04.08.2017 08:18-1Я не знаю… насчёт интуитивно-понятности Вашего кода на ноде без всякого мавена
var socket = new WebSocket("ws://localhost:8097/ws"); ocket.onopen = function() { alert("Соединение установлено."); }; socket.onclose = function(event) { if (event.wasClean) { alert('Соединение закрыто чисто'); } else { alert('Обрыв соединения'); // например, "убит" процесс сервера } alert('Код: ' + event.code + ' причина: ' + event.reason); }; socket.onmessage = function(event) { alert("Получены данные " + event.data); }; socket.onerror = function(error) { alert("Ошибка " + error.message); };
Если Вам эта длиннотень нравится
WebSocketContainer container = ContainerProvider.getWebSocketContainer(); container.connectToServer(CustomClientEndpoint.class, new URI("ws://localhost:8080/path"));
непонятная… не буду Вас переубеждать…
А ещё Вам сказу… помните песню Бутусова,
-«Тут составы смяли чтобы сделать колонны»…
Так вот это об этом Вашем решении… Вставить в зависимость такого монстра как spring
org.springframework.boot
И ради этого маленького решения потянуть зависимости org.springframework.boot
.я понимаю Вы хотели показать краткость… и она из-за спринговых аннтотаций.(Но всё равно неизящно, интутивно непонятно).
Я сколько пищу на яве… и надо мне передать по сокету.(скопировать файл)… я ищу свои прежние решения, чтобы скопипастить подобную хрень.
ByteBuffer byteBuffer = ByteBuffer.allocate(1000);
try (FileInputStream file = new FileInputStream("/path/to/file")) {
byteBuffer.put(IOUtils.toByteArray(file));
А в ноде не ищу… мысль сама ложится.
Мысль: Так надо забрать из сокета(не ws)
socket.on('data',(data)=>{Работаю с данными...причём не Важно бинарные,или текстовые })
Мысль на русском эквивалентна количеству кода.
А Автору топика скажу(И больше уже не буду спорить..), что Node и завоевал
популярность ибо его коэффициент Эффективность/Простота =Очень Высок.
java тоже эффективна… но не проста.(И есть моменты, которые бы я делал только на java)
fogone
04.08.2017 18:58на котлине:
клиент
val html = URL("http://google.com").openStream().reader().readText()
сервер
fun main(args: Array<String>) { embeddedServer(Netty, 8080) { routing { get("/") { call.respondText("Hello, world!", ContentType.Text.Html) } } }.start(wait = true) }
Braidner
04.08.2017 17:21Ну-ну, вы про спринг бут слышали? Все тоже делается в пару строк, но имеем нормальную типизацию. Так что не надо пудрить мозги людям.
public class WebServiceClient { private static final String MESSAGE = "<message xmlns=\"http://tempuri.org\">Hello World</message>"; private final WebServiceTemplate webServiceTemplate = new WebServiceTemplate(); public void customSendAndReceive() { StreamSource source = new StreamSource(new StringReader(MESSAGE)); StreamResult result = new StreamResult(System.out); webServiceTemplate.sendSourceAndReceiveToResult("http://localhost:8080/AnotherWebService", source, result); } }
sshikov
10.08.2017 22:36+1Вы неправы. Я понимаю, что это коммент, а не статья, но то что вы демонстрируете — это скажем 10% возможностей SOAP. Поэтому у вас и получается такой короткий пример. И кстати, возьмите уже CXF — и у вас получится ровно тоже самое. И для остальных случаев, кстати.
Apx
02.08.2017 23:20+6Ещё пару лет понырять в js вам и удалите статью по собственному желанию))) (Java developer)
По долгу службы пришлось тоже с js работать и ничего, жив здоров и со всеми пунктами вашими уже давно живу спокойно вместе — почти как с пилящей женой)
P. S. По поводу одного потока — кто запрещает ранить несколько процессов и лоудбалансить их?
Iqorek
02.08.2017 23:22+13Вы не совсем разобрались в теме, во первых если JavaScript был ужасен, то это было до es6 и выше. Детские болезни еще не выпилили на 100%, но встречи с ними можно избежать.
однопоточный рантайм ( в 2017 году!!! )
Во первых это круто, потому что многопоточный почти никто не умеет писать. Да да, запускать потоки можно научиться за один вечер, делать это эффективно, увы. Во вторых, он не однопоточный, все IO операции производятся в других потоках и именно эти операции берут время, в одном потоке бежит только ваш код. Зато никаких блокировок, никаких контекст свитчей, никаких race condition (почти) и прочих многопоточных радостей, которые 1 наносекунду превращают в 1 миллисекунду.
отсутствие единой системы / стандартов реализации модулей
Тем не менее вопрос решен, можно выбрать один из стандартов и в принципе все будет работать
отсутствие единых стандартов структуры проекта
Это не проблема языка, некая стандартизация есть.
слабые типы с неявными ( и порой довольно странными ) преобразованиями
Например? То что они есть, не обязывают вас их использовать, иногда разные странные вещи бывают полезны.
отсутствие нормальных классов / ООП
Так ли нужен ООП? Я очень долго слышу мантру ООП, ООП, но по факту это всего лишь одна из техник написания кода, не всегда оправданная, это не панацея для написания правильного и хорошего кода. Правильный и хороший код, это тот, который делает то что надо, за минимальное время. Я видал не один килобайт, а может и мегабайт г-но кода написанного на ООП.
отсутствие единого вменяемого и работающего статического анализатора кода
Как то обходимся линтерами и заполировываем юниттестами, багов не больше, чем в других языках.
этот чудесный контекст this
Лучше вообще не использовать это слово. Как goto. Это реально. Жаль, но это одна из родовых травм, кто ж в 96м году знал, что так вот оно получится.
абсолютно дурацкая реализация pattern matching
Скорей соглашусь, но такая же проблема есть у многих, перед тем как, что то откуда то выковырять, нужно проверять, что там, что то есть.
отсутствие единой технологии работы с асинхронным кодом
Эволюция, все идет в async, в браузерах уже есть, в ноде тоже, скоро код подтянется. При чем можно использовать все методы одновременно, если в этом есть резон.
const ( который на самом деле НЕ const )
Не понял суть наезда. Можно наехать на var, но сегодня его и использовать моветон.
абсолютно безумный npm с пакетами качества «братишка я тебе покушать принёс»
Да но, работает очень просто и надежно. На других языках часто нужно хорошо попрыгать с бубном, пока братишка соизволит хоть что принести.
В общем JavaScript ужасен как ни крути, но он имеет бешеную популярность благодаря баблу и низкому порогу входа.
Нет, он не идеален, но
- Удивительно, но производительность у него не хуже чем у той же java или c# (проверял)
- Нет заморочек с мультипоточностью, при этом асинхронность остается
- Кроссплатформенность и обратная совместимость
- Удобные инструменты, которые просто работают, как то например упомянутый npm
Это мои плюсы, а еще несколько лет назад я был в вашем лагере.porn
03.08.2017 08:48+2Я бы не стал приводить npm как плюс js. Посмотрите на composer хотя бы.
Iqorek
03.08.2017 09:48+3Это не плюс js это плюс nodejs, который поставляется с очень удобным и простым менеджером пакетов. Можно спорить о его недостатках, они как и везде есть, но у него есть неоспоримое достоинство, он тупо работает из коробки, при этом он не делает лок на себя, вы можете использовать любой другой менеджер пакетов.
franzose
03.08.2017 13:06-1Во первых это круто, потому что многопоточный почти никто не умеет писать.
Ну, если уж писать на языке, который поддерживает многопоточность, так надо учиться делать это правильно и безопасно.
Iqorek
03.08.2017 14:21Допустим делать безопасно несложно, а вот с правильностью проблема. Мультипоточное программирование на порядок сложней однопоточного и понять, где вы теряете производительность, бывает очень тяжело. То есть в теории все понятно, избегайте блокировок и синхронизаций. Пример из жизни, был у нас крутейший мультипоточный сервер, все вроде бы написано по феншую, с неблокирующим IO, immutable данными чтобы не синхронизировать между потоками и так далее, но производительность все равно не была впечатляющей. Где мы упали? В самом неожиданном месте, логер у нас, как оказалось был блокирующий (один из популярных опенсорсных на то время), то есть когда несколько потоков пишут в лог, а писали мы много и не писать не могли, только один из них это делает, остальные уходят в контекст свитч со всеми вытекающими. По сути у нас все потоки работали хуже, чем если бы у нас был один поток, потому что в этом случае у нас хотя бы не было контекст свитчей. Ну сделали мы свой логер неблокирующим, получили другую проблему, потоки работают с данными в памяти и это очень быстро, а лог то он в файл пишется, а это хоть и быстро, но как минимум в несколько тысяч раз медленней, поэтому при большой нагрузке очередь лога начинала расти, как снежный ком, получалось или надо логи дропать или тормозить всех, подождите мы за вами записывать не успеваем. В конечном итоге мы решили и эту проблему и еще несколько которые вылезли по пути. Это я к тому, что не всегда ваш код виноват в просадке производительности. В мультипоточности очень легко выпустить весь пар в свисток и не заметить этого.
greendimka
03.08.2017 16:19+1Вам лучше не лезть в проектирование с такими суждениями. Как один поток спас бы вас от тормозов лога? (ах, ну да — контекст свитч бы отсутствовал — наверное помогло бы :)
Пишите на диск уйму сообщений? Кэшируем много сообщений — и пишем один блок, кэшируем много сообщение — и пишем один блок. А если каждое сообщение писать (да еще при этом каждый раз файл открывать, а записав — закрывать), то — никакая архитектура хранилища не будет справляться.vintage
03.08.2017 16:45Кэшируем много сообщений — и пишем один блок, кэшируем много сообщение — и пишем один блок.
Ось и так это делает. Если, конечно, не вызывать fsync после каждого сообщения.
greendimka
03.08.2017 17:20На уровне бизнес-логики ось этого не делает, т.к. ничего не знает о вашей бизнес логике. Ось это делает на уровне потоков.
Iqorek
03.08.2017 17:16(ах, ну да — контекст свитч бы отсутствовал — наверное помогло бы :)
Да, помогло бы. Наш сервис большую часть процессорного времени занимался именно этими свитчами, а не обработкой запросов. Переключение контекста это относительно тяжелая операция, по крайней мере по сравнению с операцией обработки запросов в нашем сервисе.
Кэшируем много сообщений — и пишем один блок, кэшируем много сообщение — и пишем один блок. А если каждое сообщение писать (да еще при этом каждый раз файл открывать, а записав — закрывать), то — никакая архитектура хранилища не будет справляться.
Вам уже ответили выше, что тоже самое делает ОС, но в начале мы так и сделали, как написал выше, очень быстро мы обнаружили проблему переполнения. Вторая проблема, это вероятность потерять последние логи, в случае креша. В итоге мы сделали логер на базе spinlock что поток хотя бы не уходил в свитч. И да, это помогло.
pnovikov
03.08.2017 17:04Вообще-то то, как выйти из описанной вами проблемы, в приличных компаниях спрашивается на собеседованиях так-то…
И еще у меня ощущение, что вы путаете многопоточность и асинхронность.
izzholtik
04.08.2017 09:07+4Вы сейчас всерьёз приводите кривой логгер как пример сложности многопоточного программирования?
Iqorek
04.08.2017 09:43Только логгер не самописный, а из семейства log4, на тот момент один из популярных и использовали его не только мы. Но проблему до нас никто не видел да и мы ее далеко не сразу обнаружили.
pnovikov
03.08.2017 17:07+4Господа, я может что-то путаю, но в мою молодость умение писать многопоточный код, знание примитивов синхронизации и (желательно) идиоматических задач многопоточности (обедающие философы, читатель-писатель и т.д.) входило в базовый набор навыков программиста, который проверялся на собеседованиях еще до конкретных вопросов по языку/технологии. Это вроде как было общей теоретической базой, которой обучали во всех вменяемых IT-ВУЗах.
Сейчас что-то изменилось? Я что-то пропустил?Iqorek
03.08.2017 17:46+1Многопоточность это сложная тема, там много неочевидных вещей, которые нельзя просчитать в голове. Даже если вы хорошо знакомы с теорией. Очень легко не только не выиграть в производительности, но потерять. Я всегда делаю тесты производительности и проверяю разные варианты, в том числе и однопоточный вариант, и другого способа узнать вы идете в правильном направлении, нет.
pnovikov
03.08.2017 17:58+2Само собой многопоточность — это сложно. Ну так а никто и не говорит что в принципе программирование — это просто. Всегда надо думать головой и просчитывать варианты.
Касательно непосредственно вашего примера — я не думаю что
а) вся проблема была в переключениях контекста (ибо тогда бы вам пришлось поубивать изрядную долю процессов на своем сервере для оптимизации)
б) что однопоточная модель, скажем, nodejs, спасла бы вас от переключений контекста, ибо как контексты бы все равно переключались, ибо как, скажем, nginx, стоящий перед вашей нодой — будет создавать новые процессы. Вы бы не решили проблему, а просто перенесли её на другой уровень или же вообще спрятали её в нерешаемые дебри.
А вот как раз вменяемая многопоточная модель с shared-данными вас могла бы спасти (отдельный поток на запись логов, да). Но то ж нет. То ж надо синхронизацию писать, ведь так? :) На крайний случай — асинхронный сервер для логов и какой-нибудь rabbitmq, чтобы не было проблем с логами в случае крэша основного процесса.vintage
03.08.2017 18:03Логи замечательно реализуются через wait-free алгоритмы. Не нужны тут никакие синхронизации.
Iqorek
03.08.2017 18:46+2Да, но что делать если в бассейн наливается больше воды, чем выливается? Когда есть блокировка, процесс который генерирует логи, ждет и новые логи не создает, хотя при этом простаивает. А если его не блокировать, пока я пишу первый лог, он мне еще 10 настрогает. Решений несколько:
- Выбрасывать логи если возникло переполнение (не наш вариант, нам нужны все логи, хотя кому то может и подойдет)
- В момент переполнения, начинать блокировку потоков, которые пишут в лог, пока все хорошо,
будет работать быстро и без блокировок, но в случае превышения емкости, сервис начнет подлагивать (ввиду того что у нас это была штатная ситуация, этот вариант тоже отмели) - Использовать спинлоки, которые тормозят процесс на время записи лога, но не делают переключение контекста (и это то, что мы выбрали, как наименьшее зло)
vintage
03.08.2017 19:51+2Да тут даже спинлоки не нужны — хватит и атомиков. Создаём циклический буфер, один поток пишет, другой читает. На каждый поток по буферу. Логер читает из буферов раундробином. Потоки перед записью проверяют не полон ли буфер и пока полон — крутятся в бесконечном цикле. Пока логер успевает разгребать сообщения — потоки пишут в него мгновенно (записали сообщение в свободное место буфера, сдвинули индекс конца). Как перестал успевать — самые активные писатели начинают периодически засыпать.
copist
04.08.2017 15:01Кстати про this, в глаза бросилось
Это же язык GoLang, я не ошибся?
Это как расшифровать?
/// Limit channel to 512B by default this( int size = 512 / Message.sizeof - 1 ) // что этот this делает? { enforce( size > 0 , "Channel size must be greater then 0" ); this.messages = new Message[ size + 1 ]; // а этот? }
Iqorek
03.08.2017 18:33Само собой многопоточность — это сложно
Так js — это отличный выход, получить высокую производительность, но без явной многопоточности.
вся проблема была в переключениях контекста
Нет конечно, но из всех больших бутылочных горлышек, это был крупный улов.
А вот как раз вменяемая многопоточная модель с shared-данными вас могла бы спасти
Не соглашусь, если вы хотите скорости и многопоточности одновременно, общие данные между потоками зло, потому что будут блокировки, их не избежать. Операции над объектами в памяти очень быстрые,
наберите в консоли браузера
1 миллион сложений мой браузер сделал за 25мс. Если этот код разбить на два потока (не в js кончено, в другом языке) и добавить синхронизацию между потоками, а как без нее, я даже боюсь предположить во сколько раз возрастет время исполнения.let sum = 0; console.time('for 1 million'); for(let i=0;i<1000000;i++) {sum+=i}; console.timeEnd('for 1 million'); console.log(sum)
Универсального рецепта нет, но нужно стремиться к тому, чтобы одновременно одни и те же данные обслуживал только один поток.
асинхронный сервер для логов и какой-нибудь rabbitmq, чтобы не было проблем с логами в случае крэша основного процесса.
Мы уперлись в недостаточно быструю операцию записи в файл, запись в сокет рабита ничем не быстрей.pnovikov
03.08.2017 18:47+2Если этот код разбить на два потока (не в js кончено, в другом языке) и добавить синхронизацию между потоками, а как без нее, я даже боюсь предположить во сколько раз возрастет время исполнения.
Простите, а зачем этот код вообще выполнять в 2 потока? Если вы думаете что многопоточность — это такая волшебная таблетка, которая просто все ускоряет — вы очень сильно ошибаетесь. Я подскажу: если перед операцией
sum+=i
вы добавите, например, скачивание картинки — то я даже боюсь предположить во сколько раз сократиться время исполнения, если это делать в 2 потока. :)
Не соглашусь, если вы хотите скорости и многопоточности одновременно, общие данные между потоками зло
Очень даже добро, если правильно выстроить обращения к общим данным. Кроме того, выше вон человек заметил про что существуют механизмы неблокирующей синхронизации (wait-free), с которыми работа с общими данными становится дюже быстрее. Погуглите по слову "concurrency".
Так js — это отличный выход, получить высокую производительность, но без явной многопоточности
Я открою для вас секретик: любой асинхронный вызов в nodejs так же — вы будете смеяться — переключает контексты. Откройте исходники и почитайте — там внутри тредпул, если я правильно врубился. Так что js в данном случае — как раз плохое решение. Хорошее — это C с posix-тредами. Но, повторюсь, это только в случае если проблема действительно в переключениях контекста, во что я по-прежнему не верю. :)
Мы уперлись в недостаточно быструю операцию записи в файл, запись в сокет рабита ничем не быстрей.
Сомнительное утверждение. Запись в сокет не приводит к движению магнитной головки диска (если у вас обычный HDD, а не SSD).
Iqorek
03.08.2017 19:00-1Простите, а зачем этот код вообще выполнять в 2 потока? Если вы думаете что многопоточность — это такая волшебная таблетка, которая просто все ускоряет — вы очень сильно ошибаетесь.
Воот! Народ именно так и думает. Точнее не думает, а просто разделяет код на несколько потоков и довольный идет пить кофе. Это я встречал, не то что неоднократно, я даже не всегда был в состоянии доказать человеку, что он неправ. У него в голове, два потока работают параллельно, значит быстрей. Все, разговор окончен. Что есть цена у каждого потока, до этого доходят далеко не все.
Я открою для вас секретик: любой асинхронный вызов в nodejs так же — вы будете смеяться — переключает контексты. Откройте исходники и почитайте — там внутри тредпул, если я правильно врубился.
Он переключает контексты, но не в основном потоке, основной поток бежит пока операционная система не заморозит.
Сомнительное утверждение. Запись в сокет не приводит к движению магнитной головки диска
Попробуйте написать простенький клиент сервер, который будет через сокет передавать мусор, а сервер будет считать сколько байтов в секунду он получил. Тоже самое с файлами, напишите приложение, которое в течении 10 секунд пишет мусор в файл и посмотрите сколько мегабайт он успеет записать в секунду. Ну и третье, приложение, которое копирует один буфер в другой, но в памяти, тоже сколько оно успеет скопировать за одну секунду.pnovikov
03.08.2017 19:09+4Воот! Народ именно так и думает. Точнее не думает, а просто разделяет код на несколько потоков и довольный идет пить кофе.
Ну дык и как смена технологии спасет вас от тупого разработчика, который ею пользуется? Тут народ надо обучать, а не предлагать супер-технологии, которые избавят от всех проблем. И это, кстати, одна из проблем JS-а: он скрывает проблему, говоря "вот пишите как мы, а о потоках не думайте". Мне не кажется что такой подход может довести до добра.
Он переключает контексты, но не в основном потоке
Простите великодушно, но переключение контекста не может происходить "в потоке". Оно происходит между потоками или между процессами. Вы что-то путаете. Если я правильно понял исходники nodejs — то там все еще веселее: в рамках якобы "однопоточной" модели у вас с каждой операцией запускается (берется из тредпула, но я для простоты говорю "запускается") неопределенное количество потоков, на которых просто висят коллбеки. И это еще бОльший ад чем использование многопоточности явно — в последнем случае у вас хотя бы есть контроль над ситуацией. Для сравнения: C# использует для тех же целей I/O completion ports, которые не создают лишних потоков.
Попробуйте написать простенький клиент сервер
Потом
0xd34df00d
04.08.2017 06:30+2Если этот код разбить на два потока (не в js кончено, в другом языке) и добавить синхронизацию между потоками, а как без нее, я даже боюсь предположить во сколько раз возрастет время исполнения.
А зачем там синхронизация? Один поток суммирует свою часть и получает свою частичную сумму, другой — вторую, а потом, когда они оба завершаются, обе частичные суммы складываются, и получается результат.
И этот вариант тоже можно чуточку оптимизировать.maxpsyhos
04.08.2017 08:50-2Вы так пишите, будто эти потоки есть сам по себе как данность.
Второй поток надо создать, запустить, подождать, пока он выполнится, и потом сложить. Опять же у ОС диспетчеризация потоков тоже не бесплатна.
И вот если на всю эту канитель накладных расходов будет более 12,5мс (максимальный теоретический выигрыш от параллельности), то в результате всё будет работать только медленнее.
И то это всё только при условии, что у нас есть ещё одно свободное процессорное ядро, иначе эти потоки просто встанут в очередь и точно так же выполнятся последовательно, только ещё с накладными расходами на содержание потоков, и всё гарантированно будет работать медленнее.
Для чего-то реально тяжёлого в ноде можно запустить отдельный поток с изолированным контекстом, и обмениваться данными через сообщения или внешнюю шину событий, а для всякой мелочи достаточно и асинхронности в пределах одного потока.
0xd34df00d
04.08.2017 09:31Второй поток надо создать, запустить, подождать, пока он выполнится, и потом сложить.
Или достаточно кинуть задачу в очередь, а фиксированный тредпул её разгребёт.
И можно не ждать, пока он выполнится, а складывать параллельно.
И вообще, я тут наваял очень тривиальный и тупой бенчмарк:
Тута2:29:24 d34df00d@deadaven ~/Programming/tmp % cat main.cpp && clang++ -O3 -std=c++14 -pthread main.cpp -o main && time ./main #include <thread> #include <iostream> int main() { int sum = 0; for (int i = 0; i < 1000000; ++i) { std::thread t { [] (int& sum) { ++sum; }, std::ref(sum) }; t.join(); } std::cout << sum << std::endl; } 1000000 ./main 0,98s user 4,21s system 66% cpu 7,765 total
maxpsyhos
04.08.2017 09:58А теперь вот мне стало интересно: откуда у вас взялось это число?
Как это откуда? По условию «бенчмарка» последовательная программа отработала за 25мс (принято на слово). Если её разделить на 2 половины, то в идеальном вакууме время исполнения сократится вдвое, на 12,5мс. Если накладные расходы превысят эту цифру, значит итоговая производительность не увеличилась.
Насколько? Какова вероятность отсутствия прочих свободных ядер?
А мне то откуда знать, что у вас за машина и чем ещё она загружена? Например на небольшой однопроцессорной VPS-ке вероятность отсутствия прочих свободных ядер строго равна единице, поэтому там никакие выкрутасы с многопоточностью не смогут увеличить производительность, от слова совсем.0xd34df00d
04.08.2017 19:33Как это откуда? По условию «бенчмарка» последовательная программа отработала за 25мс (принято на слово). Если её разделить на 2 половины, то в идеальном вакууме время исполнения сократится вдвое, на 12,5мс.
А, я контекст потерял, прошу прощенья.
Если накладные расходы превысят эту цифру, значит итоговая производительность не увеличилась.
К счастью, накладные расходы на более чем три порядка меньше.
А мне то откуда знать, что у вас за машина и чем ещё она загружена?
Это вам про ваше окружение надо знать, а не моё :)
Не, конечно, если у вас на всех проектах однопроцессорные VPS'ки, то да, никакие многопоточности вам заведомо не нужны.
AndreyRubankov
04.08.2017 09:43Вы правы на счет того, что все не так просто, как описал 0xd34df00d, но все не совсем так, как вы думаете.
Второй поток надо создать
Обычно, когда готовится многопоточность, используется пул потоков, у которого есть своя очередь задач. Так что потоки создаются только на старте приложения, т.е. это не так дорого, как вы думаете.
А дальше там все еще интереснее: потоки, системный планировщик и прочее, но это тянет на небольшую статью/заметку, так что расписывать в комменте не буду.
И то это всё только при условии, что у нас есть ещё одно свободное процессорное ядро, иначе эти потоки просто встанут в очередь и точно так же выполнятся последовательно, только ещё с накладными расходами на содержание потоков, и всё гарантированно будет работать медленнее.
Тут стоит отметить, что системная диспетчеризация работает быстрее, чем программная. Как минимум, потому, что поток, в котором выполняется программная диспетчеризация так же может исчерпать кварт времени и он будет приостановлен для выполнения другого потока.
Говорить, что это будет Гарантированно медленнее – это поспешные выводы.
ps: Не стоит забывать, что за популярностью JS, NodeJS и асинхронности стоит львиная доля маркетинга и на самом деле далеко не все так красиво, как рассказывают в «рекламе».
pps:12,5мс (максимальный теоретический выигрыш от параллельности)
А можете предоставить источник? Я так полагаю, вы читали какую-то научную работу на эту тему?maxpsyhos
04.08.2017 10:09Говорить, что это будет Гарантированно медленнее – это поспешные выводы.
Не согласен. Если у вас есть ровно одно свободное ядро, на котором надо выполнить 1млн операций, то как их не диспетчерезируй, быстрее они этого не выполнятся.
ps: Не стоит забывать, что за популярностью JS, NodeJS и асинхронности стоит львиная доля маркетинга и на самом деле далеко не все так красиво, как рассказывают в «рекламе».
Я и не утверждаю, что конкретно Нода более производтельна, чем что-то другое. Я даже наоборот, почти уверен, что нодовый неявный тредпул реализован не лучшим способом. Я только о том, что распараллеливание в реальных задачах на реальном железе не всегда даёт преимущество.
А можете предоставить источник?
https://habrahabr.ru/post/334760/?reply_to=10342966#comment_10342104
1 миллион сложений мой браузер сделал за 25мс. Если этот код разбить на два потока...
AndreyRubankov
04.08.2017 12:15Не согласен. Если у вас есть ровно одно свободное ядро, на котором надо выполнить 1млн операций, то как их не диспетчерезируй, быстрее они этого не выполнятся.
И тут стоит отметить, что в случае с программой, которая создаст несколько реальных потоков – она будет получать больше процессорного времени для выполнения своих задач, чем однопоточная нода.
допустим OS будет диспетчеризировать 9 потоков + 1 поток вашей программы.
В случае с NodeJs, в системе будет всего 10 потоков. И тут, идем интуитивно, из 1 секунды, каждый поток будет выполняться по 100 мс (это не совсем так, потому что приоритеты и т.д.), т.е. NodeJs будет делать полезные действия всего 100 мс в каждой секунде.
В случае с приложением с реальными потоками: допустим у нас будет 20 потоков (9 потоков системы + 1 поток приложения + 10 потоков которые породило приложение).
В этом случае каждый поток будет выполняться по 50 мс в секунду, итого, наше приложение получает уже 550 мс процессорного времени в одну секунду.
И пусть из них дополнительно 20 мс уйдет на планирование (а это очень много!).
Итого, NodeJs будет выполнять полезные дейсвтия 100 мс, железные потоки — (550 — 20) мс.
Но в реальности это выглядит не так эпично, т.к. есть приоритеты потоков, а отбирая квант времени у других подсистем, они будут работать медленнее, что в общем скажется на работе всей системы. Так что в реальности «железные» потоки Будут все де выигрывать, но этот выигрыш будет примерно 150-300% (зависит от многих факторов).
Но NodeJs будет выигрывать на IO операциях, для которых не нужно использовать процессор, и то, если другая система не будет использовать все тот же asyncIO подход =)
https://habrahabr.ru/post/334760/?reply_to=10342966#comment_10342104
1 миллион сложений мой браузер сделал за 25мс. Если этот код разбить на два потока...
Есть закон Амдала, который позволяет расчитать примерный выигрыш от введения нескольких потоков.
Если кратко, то следствие: минимальное время выполнения задачи равно времени выполнения действий которые нельзя распаралелить. Потому, интуитивное «поделить на 2» – не будет работать. И это не говоря про то, что результат от запуска к запуску будет меняться, особенно в браузере, где «постороннего шума» невероятно много.
franzose
03.08.2017 23:36+2Мы в вузе не изучали многопоточность ни на одном из языков, которые у нас были: C++, C#, Delphi.
pnovikov
03.08.2017 23:53+2И я вам очень сочувствую.
Iqorek
04.08.2017 17:28Я тоже не помню, чтобы у нас упоминали многопоточное программирование, но вероятно потому, что тогда не было многоядерных процессоров и в мультипоточности не было особого смысла, все равно процессор то один.
Мы уже привыкли, но многоядерные процессоры стали быть массовыми «всего» 10 лет назад.pnovikov
04.08.2017 17:46+1А кто вам сказал про процессоры, молодой человек? Вытесняющая многозадачность появилась в unix вообще-то годах в 80х. А потом перекочевало в Windows 95 для UI. Равно как и ваше преславутое переключение контекстов. И сделано оно было для того, чтобы вы могли на одном камне сорта Pentium II слушать музыку в Winamp и смотреть интернет через netscape. Вы правда не читали об этом? Это потом уже человечество дошло до многоядерных процессоров и вопросов синхронизации кластеных вычислений. У вас блин операционная система многозадачна и многопоточна независимо от того, сколько у вас камней на матери. И как оно внутри работает — надо знать хотя бы в общих чертах, чтобы более-менее эффективно писать ПО под современные операционные системы. Поэтому это преподают в нормальных ВУЗах.
Iqorek
04.08.2017 18:12+3Многозадачность? Да, про многозадачность в частности и операционные системы, в целом, был отдельный курс. Но при чем здесь она.
Movimento5Litri
03.08.2017 13:58-10Вы не совсем разобрались в теме, во первых если JavaScript был ужасен, то это было до es6 и выше
Привет браузерам которые какакать хотели на всякие эти ваши новомодные es6 и заказчикам которым прям понос как надо чтобы работало на Internet Explorer 6.
Бабель — костыль (на это даже название намекает) что впрочем не удивительно учитывая что жаваскрипт экосистема это костыль на костыле и костылём погоняющий.
Во первых это круто, потому что многопоточный почти никто не умеет писать
Делать евроремонт почти никто не умеет поэтому Равшан и Джамшут — крутые.
Да но, npm работает очень просто и надежно.
Ага, а потом кто-то обиделся и удалил 10 строчную «библиотеку» которая только и делала что делала что добавляла буковку в начало строки и все библиотеки и фреймворки перестали компилироваться, ахренеть как надёжно.
Пакеты-вирусы это тоже показатель надёжности.
staticlab
03.08.2017 14:01+1Пакеты-вирусы это тоже показатель надёжности.
Да, это очень неприятная проблема, а как с подобным борятся composer, maven, pip, nuget и прочие?
Movimento5Litri
03.08.2017 15:06-6а как с подобным борятся composer, maven, pip, nuget и прочие?
Успешно.staticlab
03.08.2017 15:17+6Чувствуется, что это троллинг, потому что вы не знаете наверняка.
Movimento5Litri
03.08.2017 19:22Нда…
Для тех кто в танке:
Абсолютно всё равно как с этим борются другие пакетные менеджеры.
Абсолютно.
Важно то что вирусов в них нет и трёхстрочных«библиотек»микрофреймворков тоже.franzose
04.08.2017 01:16+1трёхстрочных «библиотек» микрофреймворков тоже.
Просто потому, что эти языки чуть более многословны)
VolCh
05.08.2017 11:29Насчёт трехстрочных не говорил бы так уверенно про композер. Какой-нибудь полифилл вполне может уложиться в три строки.
Zenitchik
03.08.2017 14:03Привет браузерам которые какакать хотели на всякие эти ваши новомодные es6 и заказчикам которым прям понос как надо чтобы работало на Internet Explorer 6.
От всей души сочувствую. Сам в таком же положении. Ничего, крутимся. Полифилы выручают во всех критичных случаях.
Dimensi
04.08.2017 09:06-1Просветите, что не так с this?
this доступен только у функции, которая находится внутри объекта и все.
А функции бывают с поздним связыванием и ранним. И все, что с ним не так?bano-notit
04.08.2017 12:07+1Все жалуются, что если у простой функции не привязал его сразу через
.call()
,.bind()
или.apply()
, то она может ссылаться наwindow
, А когда выносишь функцию из объекта, то она тоже теряет этот объект… Короче людям не нравится, что в каких-то местах this очевидно указывает на то, что им хочется, а в каких-то местах им нужно очевидно самим указать, на что this по их мнению должен указывать. В общем это просто не знание как работает this, не более.
IonianWind
02.08.2017 23:25+6однопоточный рантайм ( в 2017 году!!! )
ServiceWorker в браузере, cluster на сервере
отсутствие единой системы / стандартов реализации модулей ( опять же, 2017 год на дворе )
ES6-модули в браузере, CommonJs на сервере. Ну или babel везде
абсолютно безумный npm с пакетами качества «братишка я тебе покушать принёс» ( и даже вот с таким )
отсутствие единых стандартов структуры проекта ( все творят как хотят, в исходниках бывает очень сложно разобраться )ну, это уже человеческий фактор
слабые типы с неявными ( и порой довольно странными ) преобразованиями
этот чудесный контекст this ( что это значит this в этом месте кода — объект? функция? )
const ( который на самом деле НЕ const )RTFM
отсутствие нормальных классов / ООП
что значит "нормальные"? мне лично, например, и так норм :3
отсутствие единого вменяемого и работающего статического анализатора кода ( добро пожаловать в чудесный мир глупейших ошибок типа undefined is not a function )
Ну, тут самодисциплина помогает. Но да, не хватает.
абсолютно дурацкая реализация pattern matching ( паттерн матчишь пустой список / объект — без проблем, извлекаешь оттуда undefined, ты же именно это имел ввиду, да? ) и здесь опять привет cannot read property foo of undefined
а вот тут мне лично не очень понятно, что хотел сказать автор
отсутствие единой технологии работы с асинхронным кодом — колбэки, примисы, фьючерсы, async ( если в проекте более одной зависимости из npm то гарантированно в коде появятся все из них вперемешку )
Bluebird Promise.promisify в браузере, util.promisify на сервере, и коллбэки становятся промисами. Async/await — фактически те же промисы, только "подсахаренные". А фьючерсы — на фондовой бирже)
Самодисциплина по отношению к своему коду вполне нивелирует большинство пунктов.
И да, жизнь — боль ;)
le1ic
02.08.2017 23:46+6однопоточный рантайм ( в 2017 году!!! )
это самое крутое что отличает nodejs. С введением async/await наконец это вообще стало просто сказкой.
Многопоточность нужна только для CPU-intensive задач, которые вряд ли имеет смысл делать на JS, но если очень хочется, то можно использовать многопроцессность.
отсутствие единых стандартов структуры проекта
а джава что, регламентирует структуру проекта? По мне так мягкие договоренности лучше жестких навязываний
абсолютно безумный npm
что в нем безумного? Наоборот очень простая и круто работающая система без проблем с разруливанием несовместимых зависимостей.
Про размер5Мб для простого SPA
по факту докер имидж nodejs приложения может занимать 10-20 МБ, в то время как любого другого сотни МБ (джава со всеми зависимостями например)
Самый существенный косяк JS — это отсутствие целочисленных типов. И это конечно жестко.
Опциональная типизация тоже была бы nice-to-have, но для тех, кому критично есть TS.
Все остальное это какое-то непрофессиональное нытьеKoCMoHaBT61
03.08.2017 07:41+6Им не просто ООП надо. Им нужен такой ООП, чтобы ответ на вопрос на собеседовании: «Назовите три принципа ООП» «Это полиморфизм, наследование и инкапсуляция» — был правильным.
copist
04.08.2017 15:17Зато у знатоков на такой вопрос всегда есть встречный: «мы говорим про С++/Java, JavaScript или Common Lisp?
(Чьё ООП круче?)
copist
04.08.2017 15:105Мб для простого SPA — это серверная или клиентская сторона?
Серверная — вообще кайф. 5Мб кода вместе с библиотеками — это очень даже компактно. Не смотри в node_modules и в статику и всё OK.
Клиентская — это поклёп. Современный JS может очень компактно сжиматься, даже если сложный. Ещё умеет подгружаться по мере необходимости. 5Мб для фронта возможно только с учётом стилей и картинок, но это в JS уже не относится.bano-notit
04.08.2017 21:21К большому сожалению сжимать нормально умеет сейчас только гугль слож компиллер, но писать под него мало кто хочет, потому что он всё же не умеет в commonjs модули, которые вроде как сейчас являются из-за ноды стандартом. А аглифай по сравнению с гугловским отродием — просто мошка, по факту.
k12th
03.08.2017 00:50+6Все гораздо проще. Миром правит информация. Информация должна доходить до потребителя. Так как ее много, то чтобы ее донести, нужен софт. По факту оказалось, что веб — самый удобный способ доставки софта.
Никакого глобального заговора корпораций нет. Сидите спокойно в своем OTP.
bano-notit
03.08.2017 01:56+9There are only two kinds of languages: the ones people complain about and the ones nobody uses.
rumkin
03.08.2017 03:27Да, вы не нервничайте так, скоро WebAssembly появится в продакшене, сможете писать хоть на брейнфаке. И бек, и фронт. Правда все равно запускать будете из JS)))
kekekeks
03.08.2017 09:43+2В вебассемблю до сих пор потоки не завезли. И возможность использования языков с GC (ну или возможность прикрутить свой GC). Когда будет — не известно. Но они работают над этим™.
rumkin
03.08.2017 12:13+3Рано или поздно это все появится. Правда на деле от WebAssembly у автора случится еще больший баттхёрт: каждый язык начнет тащить на фронт свой рантайм, а говнокодить начнут и на его любимом ерланге.
Lofer
03.08.2017 03:39-4Судя по направлению развития JS начинает быть похожим на другие решения.
А если смотреть в сторону WebAssembly, то похоже JS многих «достал», и наконец решили сделать нормальное решение.
DeLuxis
03.08.2017 07:15-3Порог вхождения очень низок. Каждый второй сайт в интернете тормозит из-за кривого js.
Вся надежда на WebAssembly, как только сделают API для DOM.staticlab
03.08.2017 08:24+2Вся надежда на WebAssembly, как только сделают API для DOM.
Как только сделают API для DOM, начнётся вой, что этим API пользоваться неудобно. Затем может быть даже придумают аналоги jQuery. Но дело в том, что DOM сам по себе весьма тормозной, и на каждом из языков придётся делать какие-либо view-библиотеки на основе Virtual DOM или чего-либо подобного. Скорее всего, и фреймворки какие-то придумают.
Опять же, другим языкам скорее всего придётся тянуть за собой многомегабайтные рантаймы. Особенно критично это будет, если разработчики решат использовать для интерфейса не DOM, а Canvas или WebGL. В таком случае появится ещё зависимость на GUI-библиотеку.
i360u
03.08.2017 09:46+3Тормозит cам DOM, и он будет также тормозить с API из WA. Если разработчик умеет оптимизировать работу с DOM — ничего не будет тормозить и на JS. WebAssembly — он какбе для другого и кардинально ускорить свое приложение вы сможете разве что написав свой альтернативный сильно упрощеный DOM с рендером, к примеру, в WebGL.
nuald
03.08.2017 08:21+4Позвольте мне рассказать, как так получается, что для backend-а используются неподходящие технологии — так уж получилось, что я сам был виновником такого, и теперь из-за моего решения страдают другие разработчики (впрочем, они бы страдали и так и так, и я, наверное, все-таки смягчил ситуацию). Чтобы не быть голословным, я говорю про UTM-устройства FortiGate и про использующийся там Python в backend-е (сисадмины наверное знакомы с этими устройствами, хотя в России они вряд ли сильно распространены).
Все началось, когда другая команда, работающая над FortiController (менеджер этих железок) внедрили там PHP для UI. Им было это сделать очень просто, т.к. они использовали современный Linux, и им просто надо было написать пару расширений для PHP, чтобы он нормально заработал. Наш CTO загорелся идеей скриптования в backend-е и начал это активно продвигать (его понять можно — до этого была возможность только рекомпиляции и обновления прошивки даже для малозначительных изменений). Нас поставили перед фактом — внедряйте PHP в FortiGate, и чтобы это было готово уже вчера (ибо конкуренты не дремлют).
Я был очень сильно против, и после длительных дискуссий с угрозами увольнения мне сказали — предложи что-нибудь работающее и лучше, тогда подумаем. И мне дали всего 2 недели. Для контекста: FortiGate — это весьма кастомный Linux со своим ядром, файловой системой и никакими менеджерами пакетов. По сути, основное ПО на железке — это один исполняемый файл, в котором несколько точек входа (соответственно, ls и rm отличаются только точкой входа в этом файле). Как бы я не хотел внедрить что-нибудь достойное типа того же go-lang, я просто не мог заставить его работать в отведенное мне время. Другое условие — чтобы мы могли найти разработчиков. В итоге мне пришлось выбирать между JS, Python и PHP (я потом часть работы оформил в небольшую статью). К счастью, в то время V8 имел какие-то проблемы с нашим ядром (какие-то ioctl запросы не работали), поэтому несмотря на то, что мой непосредственный начальник хотел выбрать JS, я смог уговорить его использовать Python.
Я, конечно, упускаю много деталей, но выводы я сделал: выбор технологий иногда определяется не самой технологией (ее плюсами и минусами), а ограничениями (например, время внедрения) и кадрами. И к сожалению, кадры на западе — это весьма плачевное зрелище. Рынок наводнен выходцами из Китая и Индии, любовь к профессии заменена на жажду легких денег, клановое мышление заставляет их покрывать друг друга и просто отторгать всех талантливых и самостоятельно думающих разработчиков в сторону. От этого и уровень — найти JS-разработчика намного проще (даже найти нормального Python-разработчика было проблемой).
P. S. Хотел бы отметить, что я как раз недавно плотно работал с сотрудником Facebook-а, который пишет на OCaml — на нем разрабатывается Infer. Полное покрытие тестами у них не всегда есть, иногда они полагаются только на интеграционные тесты. Так что не стоить думать, что у гигантов софтоиндустрии все прекрасно, там тоже есть немало проблем.
flancer
03.08.2017 08:29+14Язык для разработчиков должен быть простым и распростаненным. Язык для "элитных программистов" может быть любым. Но желательно "с высоким порогом входа" — чтобы отсекались "всякие недоумки"."Elixir / Erlang / Lisp / Haskell / любой другой язык с хорошим дизайном" — кодовые слова, по которым "элитные программисты" находят друг друга.
Я свои первые web-приложения писал на LotusScript. На Lotus, мать его, Script! И не ныл, что тип скобочек меня не устраивает. Потому что препод в универе донес до меня простую мысль — программировать можно на любом языке, который понимает компьютер. Хоть в машкодах, хоть брейнфаком.
Дружище Strain, JavaScript популярен прежде всего потому, что браузеры другого языка не понимают. Все. Были попытки встроить в браузеры и ActiveX, и JavaApplets, и Dart. Но единственный язык, который понимает большинство браузеров — это JS. Нет никакого заговора мирового капитала против горячо любимых вами "языков с хорошим дизайном". За 300% прибыли капитал идет на любое преступление, а использовать уродливый с арихтектурной точки зрения язык в бизнесе он начинает с 0.01% прибыли. Как только тот же Erlang сможет перебить хотя бы на ту же самую сотую процента прибыль, приносимую JS'ом — бабло рекой потечет в Erlang.
А пока что не Haskell пролазит на фронт, а JS осваивает бэк. Как тут советовали коллеги чуть выше — "сидите спокойно в своем OTP". Читайте обнадеживающие новости про Ocaml. Берегите свое психическое здоровье. А зарабатывание денег оставьте девелоперам — людям с крепкой психикой и редуцированным чувством прекрасного.
Neikist
03.08.2017 09:05-2Потому что препод в универе донес до меня простую мысль — программировать можно на любом языке, который понимает компьютер. Хоть в машкодах, хоть брейнфаком.
Это все хорошо, но вот что я вижу в ваших словах: бабло, бабло, на чем угодно бабло… А как же удовольствие? Интерес? Ведь в программирование за этим идут в первую очередь? (не мне жаловаться, я вообще с 1с извращаюсь, впрочем коллегам мое нытье об отсутствии хоть какого ООП, статической типизации, анонимных и функций первого класса тоже надоело)))flancer
03.08.2017 09:40+9Мы видим то, что хотим видеть. Программировать за интерес и удовольствие можно — github предоставляет поддержку таким начинаниям. Но за окном капитализм — вы ведь не за интерес с 1С извращаетесь, не так ли? В сутках 24 часа, 11 — на добычу денег (с обедом и дорогой), 6-7 на сон, остается еще 6-7 часов. Вот и получайте удовольствие — в свое свободное время. А если хотите и удовольствие получать от работы, и деньги — научитесь получать удовольствие от программирования на Java/C/C++/C#/Python/VisualBasic/PHP/JS/Perl/Ruby/...
Программировать машины — это работа, а не искусство. Поэтому не нужно тут сопли размазывать, что молоток у тебя не с той ручкой. Бери что есть и забивай гвозди. Не любишь гвозди — бери пилу и пили. Не нравится инструмент — сделай свой. Это я про автора статьи, если что. Уж извините за выброс эмоций.
А по поводу 1С — меняйте работу. Возьмите любой язык из популярных, который нравится чуть больше остальных, и развивайте свои навыки на нем. Всегда побеждает тот волк, которого ты кормишь.
Все языки несовершенны по-своему. Чтобы понять, в чем именно, нужно просто достаточно долго попрограммировать на этом языке.
irbis_al
03.08.2017 09:47-3А вот Вы знаете не согласен… что программирование это работа, а не исскуство…
Есть выражение, работай так, как будто тебе не нужны деньги.
И Кто в моей конторе(я сам предприниматель) так работает… у того качественней код(и кстати те и больше всех получают и теми кадрами я поистине дорожу)… а те кто за бабули… типа выполнил ТЗ и там трава не расти… и сразу давай мне оплату… я ж тут не зря (-|-) рвал… у тех и код приходится переделывать и всегда им подсознательно подыскиваю замену.flancer
03.08.2017 10:04+7Если бы программирование было искусством, то за шедевры платили бы миллионы, а все остальное — просто выкидывали в мусор. Но это не так.
Программирование — это технология. Шедевр неповторяем, а технология — наоборот, обеспечивает повторяемость достижения результата. Ваше замечание по поводу того, что работники "только за деньги" выдают на-гора некачественный продукт справделиво для любой профессиональной деятельности — строитель, ремонтник, учитель, медик,… Как справедливо и то, что в любой профессии есть свои гении, чью работу можно считать искусством. Так что программирование настолько же искусство, насколько искусство профессия строителя.
wladyspb
03.08.2017 12:04-4Я бы всё же скорректировал сравнение — манки-кодинг настолько же искусство, насколько искусство — профессия строителя. А программирование как искусство — сравнимо с работой архитектора, и места для творчества обычно хватает.
copist
04.08.2017 15:25А как же удовольствие?
Программирую на нескольких языках с одинаковым удовольствием. И как-то норм всё с баблом.
Язык — это только инструмент. Важнее то, что на нём делается. Предмет важнее инструмента.
ValdikSS
03.08.2017 10:33Причем здесь браузер? Речь же про бекенд.
flancer
03.08.2017 12:10+4Согласен, не всем очевидно. JS пролазит на backend, потому что на фронте для него нет альтернатив. У меня был опыт создания фронта на GWT (Java) — пример проникновения бэкенда на фронт, и опыт создания бэкенда на nodejs (обратный пример). Дебажить в браузере GWT-шный код, да даже просто смотреть на результат преобразования java2js — то еще удовольствие.
Многие web-программеры мечтают использовать одни и те же либы на фронте и на бэке (бизнес-логика-то похожая). JS единственный дает им такую возможность native'но. Остальные — через JS (за java applet'ы ничего не говорю, ибо не взлетело).
pnovikov
03.08.2017 12:15+3Вставлю 5 копеек: бизнес-логика-то похожая, но на черт побери не та же самая! Реально общего между бэком и фронтом по коду — это модели, которые туда-сюда пересылаются. Ну может еще кусочек валидации. В остальном — бэк прибит гвоздями к контексту источника данных, а у фронта такой радости нет. Как следствие — обязанности и код довольно сильно разделен и имеет не так много общего, как кажется.
Единственный аспект, в котором изоморфный подход себя оправдывает — это шаблонизация. Круто когда на сервере и на клиенте можешь срендерить одинаковый HTML не дублируя кода. Реально, без шуток круто. Но выворачивать это обстоятельство чуть ли не в отдельную идеологию — попахивает распилом проектных бюджетов :)staticlab
03.08.2017 12:22+2На самом деле в серьёзных проектах ради изоморфизма нет смысла полностью всю бэкенд-логику писать на JS. Достаточно непосредственно самого рендеринга и валидации. А весь API писать в отдельном приложении на любом другом языке.
copist
04.08.2017 15:31Вы не представляете, какими бюджетами надо обладать, чтобы скормить гуглоботу, бингу и яндексу фронт в 2М уникальных HTML страниц, написанный на неизоморфном JS в виде SPA. Кровь, пот, слёзы, маты и периодическое выпадание из поискового индекса. Никому не посоветую теперь делать публичное SPA на неизоморфном JS. Лучше забыть про PHP/Python/Ruby и прочее если фронт будет в виде SPA и открыт для индексации поисковиками.
0xd34df00d
04.08.2017 19:35Спасибо за совет, конечно, но как-то неплохо получается совмещать приятное с полезным, и зарабатывать деньги на приятных языках.
Sna1L
03.08.2017 08:42+5Не люблю JS, но не могу не признать, что сам язык становится все лучше и лучше.
Сейчас нелегкая судьба заставила работать с реактом (сам я рельсовик), так я был приятно удивлен новыми фишками языка. Даже элементарная стрелочная нотация — это уже огромный шаг в сторону удобства и красоты.
Правда, вводит в заблуждение то, что это не сахар надfunction()
(this по-другому работает), но это разовая проблема, имхо (даже если ты не читал документацию, то достаточно быстро поймешь, что что-то не так).
Относительно магии
this
и отсутствия классов — это просто непонимание парадигмы языка, как по мне. В хаскелле вот тоже нет ооп-классов (AFAIK). И знаете, почему это не является проблемой (как мне кажется)?
Потому что ни у кого не возникает желания писать на нем в ООП-стиле. А вот джаваскрипт все пытаются натянуть на джаву/руби/другое-класс-ооп.
Достаточно разобраться в фундаментальных для языка вещах и непонятки по поводуthis
и прочего пропадут. Мне вот не нравится синтаксические новшества, связанные с классовым ООП. Готов поспорить, они появились как раз из-за того, что люди не хотят понять язык, а хотят писать на чем угодно одинаково (наводит на мысль о Scala-программистах, которые пишут на ней, как на Java).
В общем, это не баг, а фича.
Простите за сумбур, просто хотелось высказаться. Меня тоже волнует (беспокоит?) растущая популярность JS
0xd34df00d
04.08.2017 19:39В хаскелле вот тоже нет ооп-классов (AFAIK). И знаете, почему это не является проблемой (как мне кажется)? Потому что ни у кого не возникает желания писать на нем в ООП-стиле.
Следующий естественный вопрос — почему такого желания не возникает. Рискну предположить, что потому, что там есть более удобные и мощные инструменты.
А для ООП-стиля (ну, с объектами и методами) в хаскеле, кстати, есть линзы.
blazer
03.08.2017 10:04-2Последних 5 лет работал с Ruby и Ruby On Rails, последние 3 месяца осваиваю Meteor JS и делаю новый проект на нам. Я искренне люблю руби и рельсы, но в 2017 году глупо не видеть того, что 90% разработки перешло во фронтэнд, а там кроме JS вариантов просто никаких нет. А если писать все на одном языке – то уже и разделение на бэк и фронт отпадает само собой, как и куча костылей для поддержки двух языков на одной платформе. Да, JS не так изящен, как Руби, но ES6 это большой шаг вперед, и он не последний. А то что Javascript существовал в таком виде лет 20 и не менялся, как раз таки говорит о том, что язык этот отнюдь не дерьмовый. MVC архитектура в современных условиях веб-разработки уже не актуальна. Вообщем, я долго ломался, переходить или нет, но когда узнал, что в ES6 больше не нужно ставить ";" в конце строк, мои колебания закончились)) Перешел окончательно, чему весьма рад. Rails впрочем может использоваться в проектах, которые не требуют фронтэнда.
vintage
03.08.2017 10:26+8MVC архитектура в современных условиях веб-разработки уже не актуальна.
Тот-то все сейчас молятся на Redux, который является реализаций FLUX, которая является частным случаем MVC.
Вообщем, я долго ломался, переходить или нет, но когда узнал, что в ES6 больше не нужно ставить ";" в конце строк, мои колебания закончились))
Она всегда была опциональной.
pnovikov
03.08.2017 11:14+16А я вот согласен с автором. Блин, ребята, вся история программирования — это история о строгой типизации. О борьбе человека против никак не регламентированных кусков памяти в попытках обуздать эту стихию и сделать её хоть сколько-нибудь структурированной.
И тут мне в личку приходят обезумевшие JS-фанаты и заявляют что «строгая типизация — говно, все скоро от неё откажутся и будут писать на нетипизируемых языках», после чего вываливают еще тонны личных оскорблений как на меня, так и на мой любимый C#.
Далее. Хочу дополнить автора тем фактом, что судя по разброду в JS-технологиях и отсутствию одного стандартного решения хоть в каком-либо аспекте (возьмите хотя бы 5 популярнейших пакетных менедж… стойте, пока я писал этот пост — сделали шестой) — проектированием фреймворков на JS заняты люди без опыта проектирования и умения договариваться. Нуу… ладно, положим какой-то опыт проектирования у некоторых людей из JS-коммьюнити все же есть, но все эти спецы работают на крупные корпорации и делают штуки навроде React-а (надеюсь, у них-то нет времени кричать что строгая типизация скоро вымрет). С ними наверняка конкурирует еще кто-то. Все остальное развивается мягко говоря, хаотично. И это тот случай, когда рыночная «здоровая конкуренция» как раз-таки не приводит к выбору оптимального решения, а скорее засоряет эфир кучей разнокалиберных поделок неизвестной степени пригодности к использованию. Почему? Ответ прост — хайп.
И вообще, слово этого года — «хайп». Очень, очень понравилось выражение автора «хайп дривен девелопмент». Корпорации вкладывают миллионы долларов в пиар, конференции с печеньками, трансляции и книги, блогеры пишут пресс-релизы — и все это вместо того чтобы просто дать попользоваться технологией всем тем, кто желает ей попользоваться и уже на месте решить хороша она или плоха, какие задачи она решает хорошо, а какие плохо. Но нет, вместо естественного процесса смерти неэффективных решений мы имеем толпы хомячков, которые услышали про React/Angular/nodejs/ватевер и бездумно на него молятся, без разбору поливая шоколадного колера субстанцией всех, кто посмеет им возразить и указать на недостатки. Вот примерно таким макаром JS-фанаты мне давеча заявили, что «писать в многопоточных средах в 2017 — это **ня полная».
В общем, что хочу сказать. Читающий, должно быть, уже заметил что сама технология тут ни при чем. JS — нормальный язык для своих задач, с некоторыми… скажем так, архитектурными особенностями. И эта тема стала бы максимум — местом в документации, с которым ознакамливается всякий, кто начнет разрабатывать на JS. Но тут пришли люди, которые сказали, что архитектурные особености JS — это не баг, а фича, а все кто не согласен — должны идти лесом. Чуете о чем я? Проблема не в технологии, а в людях и сообществе вокруг этой технологии (ИМХО именно на этом в статье надо было сделать акцент). Я еще никогда не встречал более слепо верующего и агрессивного сообщества чем JS-разработчики. Я еще никогда не встречал более агрессивно продвигаемых технологий чем JS-стек.
Очень надеюсь, что скоро это все закончится.pnovikov
03.08.2017 12:03+8Кстати, раз уж на то пошло. Хочу обратить внимание еще на парочку этюдов, связанных с хайпом.
Все в курсе, что у JS низкий порог вхождения. Начать писать просто, никакого инструментария не нужно (блокнот да браузер). Базовый синтаксис прост до безобразия. И вот мальчик пубертатного возраста берет в руки этот набор инструментов, делает какую-нибудь пакость за пару дней. А дальше? А дальше предается упоенному самопиару — пишет про это статьи, записывает видео, публикует в npm, вероятно даже выступает на конференциях. В общем получает удовольствие от процесса, удовлетворяя свое эго, а не занимаясь, черт побери, развитием технологий. Нет, ну а что? Представьте что вам 20, вы занимаетесь поддержкой сайта какого-нибудь интернет-магазина ООО «Рога и Копыта», на плюсах не писали, в базы данных умеете на уровне phpMyAdmin, не знаете структур данных и алгоритмов. И тут у вас появляется возможность сделать не хвост собачий, а ажно целый opensource-проект, о котором всем можно рассказывать и с которым вас будут воспринимать всерьез. Красота! Вы когда-нибудь пробовали указать пубертатному подростку на то, что он занимается какой-то фигнёй? Если нет — то я вам сразу скажу что в ответ вас обольют весьма утонченными и изысканными оскорблениями. Поразительно похоже на реакцию JS-адептов на критику. :) Кстати, как не трудно догадаться, заканчивается это пиршество духа какой-нибудь забавной историей с left-pad.
Предположу, что в крупных конторах происходит примерно то же самое. Группа программистов пишет какой-нибудь фреймворк для решения какой-нибудь внутрикомпанейской задачи. При том делает это чуть ли не из интереса (все же должны получать удовольствие от работы, так? Ох уж этот либеральный подход к менеджменту!) или из имитации бурной деятельности. А потом начальству надо отчитаться куда ушли деньги и как это все поможет бизнесу заработать. В такие моменты рождается байка про «да мы же тут сделали инструмент, который превосходит аналоги!», «изобрели штуку, которая сделает мир лучше», «открыли новый подход к проектированию/рендерингу/модулям/чемуугодно». И вот уже становится как-то неловко говорить, что отдел потратил время впустую, разработчики сделали нерелевантную штуковину, которая интересна только им и вообще сожгли бюджет. Начинаются поездки по конференциям. Чем это заканчивается все итак понимают.
Ну и кулстори на десерт: я был лично знаком с человеком, который сделал небольшой фреймворк для изоморфных приложений за несколько месяцев (в рабочее время, сидя на зарплате!) и потом несколько лет занимался тем, что за деньги компании катался по конференциям, рассказывая про свое творение — и заодно про то, как хорошо работать в этой компании. А на его фреймворке, тем временем, было сделано ровно 2 работающих сайта. В итоге: фреймворк всеми забыт, компанию все итак хорошо знают, человек уволился и работает сейчас где-то в США. Только потом мне поведали что это называется «технопиар» и задумка была не сделать хороший инструмент, а разрекламировать компанию как идеальное место работы.
Такие вот дела.
timon_aeg
03.08.2017 11:43-3отсутствие вывода типов в самом языке или в каком-либо инструменте
Вычеркивайте.
class RequestMappingInfoHandlerMethodMappingNamingStrategy {}; const requestMappingInfoHandlerMethodMappingNamingStrategyInstance = new RequestMappingInfoHandlerMethodMappingNamingStrategy(); console.dir(requestMappingInfoHandlerMethodMappingNamingStrategyInstance); // RequestMappingInfoHandlerMethodMappingNamingStrategy {}
staticlab
03.08.2017 13:52+2Под выводом типов подразумевается вот это: https://ru.wikipedia.org/wiki/Вывод_типов
usr753
03.08.2017 12:13однопоточный рантайм ( в 2017 году!!! )
А как же таймеры, воркеры, и его асинхронные события? Воркеры – это отдельные потоки с изолированным контекстом. Написал даже библиотеку для удобной работы с ними: https://github.com/artnv/clientThreads
отсутствие единой системы / стандартов реализации модулей ( опять же, 2017 год на дворе )
Вычитал (не помню в какой книжке), что паттерн Модуль еще с начала 2000х использовали в JS. Это самовыполняющиеся функция которая возвращает объект с методами из замыкания. Де-факто стандарт.
отсутствие единых стандартов структуры проекта ( все творят как хотят, в исходниках бывает очень сложно разобраться )
Стандарты есть, паттерны те же самые, mvc, стили различных фреймворков.
отсутствие нормальных классов / ООП
JS – прототип-ориентированный язык, а это модель ООП. В ПП понятие класса вообще отсутствует, при этом ПП намного гибкий чем классический подход. В объектах вся мощь JS, с помощью них создается структура приложения, неймспейсы, хранятся и передаются данные как между методами так и по сети, с помощью json
отсутствие единого вменяемого и работающего статического анализатора кода ( добро пожаловать в чудесный мир глупейших ошибок типа undefined is not a function )
Это скорее мир асинхронности. Нужно понимать как браузер производит загрузку кода, в какой последовательности и когда начинает выполнять. В JS, код может генерироваться, подгружаться и подключаться динамически, в разное время. Достаточно контролировать последовательность и следить за событиями.
отсутствие вывода типов в самом языке или в каком-либо инструменте
console.log(typeof 123) // number console.log(typeof '123') // string
этот чудесный контекст this ( что это значит this в этом месте кода — объект? функция? )
this — это объект. this ссылается на внутренний контекст Конструктора (предоставляет доступ к внутренним свойствам) при создании через new, в случае отсутствия new будет ссылаться на глобальный контекст window. По сути, при создании через new возвращается объект this и все его свойства thix.x, this.y и т.д. Аналогично было бы вернуть объект с помощью return {x:1,y:2} в обычной функции. Если пугают конструкторы, this/new, можно использовать литералы объектов
отсутствие единой технологии работы с асинхронным кодом — колбэки, примисы, фьючерсы, async ( если в проекте более одной зависимости из npm то гарантированно в коде появятся все из них вперемешку )
В JS все же на событиях из-за той же асинхронности. Можно самим написать или взять готовое решение пользовательских событий по паттерну Наблюдатель/Observer, это EventManager/EventEmitter/PubSub.
Например: данные пришли с помощью ajax, публикуется событие
и все подписчики которые подписаны на него, запускаются циклом.eventManager.trigger('incomingData')
eventManager.on('incomingData', function(json) {...})
У многих есть ошибочное суждение что в JS всё легко, низкий порог вхождения и т.д. Может быть и так, в небольших приложениях, где нужно использовать пару методов JQuery, а взявшись за разработку чуть более сложного, разработчик сталкивается со своим ложным представлениям о нём. Код нужно как-то организовывать, чтобы через пару дней понять где, что работает. Придется достаточно глубоко изучить сам язык, чтобы использовать больше его возможностей, с ростом задач. Изучить API Браузера и его работу. Научится работать с асинхронностью. А уже после всего этого приниматься за библиотеки, фреймворки, а не на оборот. Впрочем зная язык можно свои велосипеды написать)mayorovp
03.08.2017 12:56отсутствие единых стандартов структуры проекта ( все творят как хотят, в исходниках бывает очень сложно разобраться )
В том-то и проблема, что с начала 2000х все пилят свои велосипеды.
RubaXa
03.08.2017 12:28Как однажды сказал Бьёрн Страуструп: «Существует два типа языков программирования — те, на которые все жалуются, и те, которыми никто не пользуется».
dklein
03.08.2017 16:51Выше его уже цитировали :)
RubaXa
03.08.2017 16:55Из этой же серии нравится интервью с Расмусом Лердорфом
«Колбаса, политика и PHP: если хотите наслаждаться ими — не смотрите, как они делаются»
PHP — просто инструмент, с помощью которого можно сколотить классные штуки. И мне нравится именно это — то, что создано с помощью PHP.
Lofer
03.08.2017 12:31отсутствие нормальных классов / ООП
JS – прототип-ориентированный язык, а это модель ООП.
Тут выбешивает несколько иное. Функция, которая не «функция», объект который не «объект» и нету четких границ где что находится. Я хочу получить нормальный «контейнер» в котором будут изолированы функции, я хочу безопастное контролируемое мной хранилище данных, и я не хочу, что бы Тот Парень как-то повлиял на мой код или данные.
Вроде много лет назад именно для этих целей и сделали классы и пространства имен.
Как это все назвать? И в JS и как решить эти проблемы, если классы это «плохо»?
Почему Вы полагаете, что Прототип-ориентированный язык это препятсвие для решения этих проблем?usr753
03.08.2017 13:28Тут выбешивает несколько иное. Функция, которая не «функция»
Да, функция это объект), например она может содержать статическое свойство
x = function() { console.log(x.static); }; x.static = 123 x(); // 123
и нету четких границ где что находится
JS как пластилин. По началу тоже непревычно было. А хорошо это или плохо ответ у каждого свой.
Я хочу получить нормальный «контейнер» в котором будут изолированы функции, я хочу безопастное контролируемое мной хранилище данных, и я не хочу, что бы Тот Парень как-то повлиял на мой код или данные.
Паттерн Модуль + Фасад. Данные и код хранятся в замыкании, без возможности доступа извне, кроме определенных методов или свойств. Та же инкапсуляция по сути. А если к этому добавить Медиатор(контроллер), который координирует работу модулей + Наблюдатель, который служит для асинхроного общения, то уже получается структура полноценного приложения.
x = (function() { var red = 200, blue = 300, green, getTotal , setGreen; getTotal = function() { console.log(red + blue + green); }; setGreen = function(arg) { green = arg; }; return { // public methods getTotal : getTotal, setGreen : setGreen } }()); x.setGreen(400); x.getTotal(); // 900
Вроде много лет назад именно для этих целей и сделали классы и пространства имен.
Пример неймспейсов
app = { model : {}, view : {}, controller : function() {} }; app.model.net = function() {}; app.model.admin = function() {}; app.model.user = function() {}; app.view.admin = function() {}; app.view.user = function() {};
если классы это «плохо»?
Классы это хорошо, но в JS их нет, в место них объекты, другой вообще подходLofer
03.08.2017 14:37-1Да, функция это объект), например она может содержать статическое свойство
Объект чего?
Если это некоторый контейнер времени исполнения который можно создать в любое время и присоединить к нему как код так и данные, ну так давайте его и назовем, к примеру, RuntimeContainer.
Если это некоторый выделенный кусок кода со свои функционалом — давайте назовем его, к примеру, function.
А так мутант какой-то :)
Пример неймспейсов
Не очень удачный пример, поскольку пространстов имен это логический контейнер. Грубо говоря это синтаксис, а не исполнение/runtime. А то, что приведено это скорее вложенные классы с эмуляцией «полного имени»
Паттерн Модуль + Фасад. Данные и код хранятся в замыкании, без возможности доступа извне, кроме определенных методов или свойств. Та же инкапсуляция по сути
Вот! Приходится использовать кучу дополнительных примочек и костылей, что бы решить типовую задачу разработки. Т.е нужно вкладывать усилия не в решение бизнес задач клиента, а в решение типовых «нюансов» инструмента.
Если бы это были новые не известные проблемы можно было бы понять. Но это же типовые и давно известные.
Классы это хорошо, но в JS их нет, в место них объекты, другой вообще подход
Это не лучшее оправдание. Приведенные выше примеры понятны и проистекают из архитектуры языка, которая просто не была готова к тем задачам, которые пытаются им решить.
Ничем хорошим это не кончится
staticlab
03.08.2017 13:36+1Функция, которая не «функция», объект который не «объект» и нету четких границ где что находится.
Что вы имеете в виду?
я хочу безопастное контролируемое мной хранилище данных, и я не хочу, что бы Тот Парень как-то повлиял на мой код или данные.
Сейчас можно инкапсулировать данные в замыкании, в том числе недоступными извне будут неэкспортированные переменные модуля. Можно использовать символы. В будущем вообще ожидается https://github.com/littledan/proposal-private-methods
Вроде много лет назад именно для этих целей и сделали классы и пространства имен.
Классы, кажется, в первую очередь решают проблему присоединения методов к данным соответствующего типа.
aen
Какая-то бессмысленная истерика.
Strain
Не истерика а набор фактов и вопрос «почему всё так?» к обсуждению
vilgeforce
В чем факт ужасности return? В том, что не нравится лично вам, не иначе.
torbasow
Чем плох return, я могу предположить. Когда у функции несколько точек выхода, это не очень надёжная конструкция. Или, вот, когда return выходит не из метода, а из малозаметной стрелочной функции внутри него, это может оказаться коварной неожиданностью.
Но фигурные скобочки и точка с запятой… Тут я теряюсь.
S_A
Единственная проблема с return в JS — нельзя перенести возвращаемое на следующую строку (будет undefined если перенести).
vintage
return такого не умеет.
mayorovp
AndreyRubankov
Известно, что функция может возвращать значение только через return (а стрелочная может и без него),
и тут назревает логичный вопрос: Если в конце тела функции нету return, то в чем здесь проблема в языке или в том, кто даже основ языка не прочитал?
vintage
А, кажется понял вашу претензию. Вы хотели выйти из метода, но не заметили, что находитесь в стрелочной функции и вышли из неё? Тут и любую другую функцию можно не заметить, если кода много, а форматирование так себе.
mayorovp
Ничего не ожидал. Я продемонстрировал что return умеет выходить из стрелочной функции.
vintage
Я изменил тот комментарий.
Было бы странно, если бы return выходил сразу из нескольких функций.
mayorovp
Да, это и правда было бы странно (хотя в Scala вроде как return так и работает). Но искать точку выхода из переусложненной функции эта странность не помогает :-)
TheShock
А зачем писать переусложненные функции?
mayorovp
Я не знаю зачем их пишут. Но читать их мне периодически приходится.
Apx
Ну хотя бы правильный пример для начала надо было написать. Потому что из примера нихрена оно не демонстрирует. Точнее не так: пример был о том что «если хочешь вернуть значение из функции — используй return». Стрелочная функция, как видно из названия — функция. Демо return statement то зачем?
mayorovp
Это (пере)упрощенный пример переусложненного метода. Тот, кто хочет выяснить почему
foo()
возвращаетundefined
, смотрит внутрь, находит return… а return-то возвращает значение не из внешней функции, а из внутренней.Вот более жизненный пример: https://github.com/jquery/jquery/blob/731c501155ef139f53029c0e58409b80f0af3a0c/src/ajax.js#L386
Да, в других языках все так же. Да, "виновата" в этом больше сама идея вложенных функций, наложенная на отсутствие культуры написания понятного кода, чем return. Но больше идей чем же этот оператор может кому-то не нравиться, у меня нет.
franzose
Вы ожидали, что console.log выдаст 42?
mayorovp
quantum
Как бы return выходит из той функции, которойнаписан
mayorovp
Ну да, так и есть.
Ryss
Вы ожидайте результат функции, которую не возвращаете
mayorovp
YemSalat
Так он же не вышел!
Ваша f() отыграла как надо, просто вы ничего не возвращаете из foo()
mayorovp
Почему не вышел-то? Он вышел из внутренней стрелочной функции, не затронув выполнение внешней.
YemSalat
Прошу прощения, опечатался, имел в виду именно что он вышел, сначала из f(), а потом из foo() (только в foo он ничего не вернул).
mayorovp
Но ведь если он вышел, значит умеет выходить? В чем в таком случае суть вашего комментария была?
dlf42
Я думаю, имелось в виду "можно перепутать return из малозаметной стрелочной функцией внутри метода с return из самого метода"
vilgeforce
Я, может, не совсем понимаю что вы подразумеваете под надежность. Но известные мне компилеры других языков не скомпилят программу, пока в каждой точке выхода не будет return. Если функция, конечно, не void func() :-)
AndreyRubankov
Есть множество языков, где есть return, но его можно не использовать (php кажется, один из таких, а еще Scala) и есть множество языков, где return отсутствует как таковой (если не ошибаюсь, к ним относится Python).
Во всех этих языках результат последнего действия будет возвращен как результат функции.
vilgeforce
В python точно есть return
flancer
есть != обязателен к использованию
DarthKotik
Но в Python он обязателен к использованию (кроме случая когда функция модифицирует переданные в неё аргументы, но не думаю что что-нибудь хоть сколько-нибудь сложное можно написать на таких конструкциях) в отличие от Ruby, где в отсутствие return функция вернёт значение, полученное при выполнение последней операции
AndreyRubankov
спасибо, значит ошибся.
nikolay_karelin
В Python функция без return вернет None.
Такие ошбки ловятся статическим (опциональным) анализом типов, но могут доставить немало "приятных" минут.
andreysmind
К ним Ruby относится :)
torbasow
А тут я перестал понимать, о чём речь. В Javascript никакой точки выхода без return быть не может, если это только не конец функции. Я имею в виду вот что: «модуль (в данном случае функция) должен иметь только одну точку входа и только одну точку выхода».
Sayonji
JS еще цветочки. А вот плюсы, они еще и объект за вас сконструируют, если вы return не напишете.
grossws
Это UB по стандарту C++
franzose
Как мне кажется, это уже не проблема языка, а то, как пишут код конкретные программисты. Потому что запутанный код можно писать на любом языке)
torbasow
Но некоторые конструкции упрощают эту задачу.
Fen1kz
Коварный, коварный JavaS… Оу, нет, просто Java.
torbasow
Я и не говорил, что Javascript хуже (или лучше Java), я просто предположил, чем может не нравиться return.
Fen1kz
Вы поддерживаете т.з. автора о том, что return — это раздражающая особенность js
torbasow
Вовсе нет. Я высказываю предположение, что именно его может раздражать. Я не утверждаю, что return обязательно должен раздражать, мне это странно.
Strain
Это моё субъективное мнение, без очевидных объективных причин, я так и написал :)
Касаемо меня — return делает код функции более запутанным, а ещё я постоянно его забываю писать. Потому что всю жизнь писал на Erlang, Elixir, Haskell и Lisp. И от забытых return — ов много проблем, потому что функция возвращает undefined без всяких предупреждений и программа потом падает в самом неожиданном месте по какой-нибудь совсем другой причине, отловить трудно. В общем получается много бессмысленной работы.
torbasow
Для меня-то как раз естественно, что если мы ничего не указываем функции возвращать, она и возвращает неопределённость. Падения по трудноотлавливаемой причине происходят не от этого, а оттого, например, что типы сами по себе втихомолку приводятся друг к другу, что там, где программист подразумевает сложение, может произойти конкатенация, а деление на ноль даст не исключение, а вполне правомерный NaN — и да, сбой в этих случаях может произойти гораздо позже, и не всегда трейс поможет.
Strain
Да, неявные преобразования усугубляют такой тип ошибки ( впрочем как и почти все типы ошибок ). Касаемо return, циклов и прочих statements — тут дело в парадигме. Видимо вы хорошо владеете императивными языками в которых есть эти statements, поэтому всё и привычно. Но в функциональных языках как правило этих statements нет, да и вообще количество statements минимально потому что всё является expression. JavaScript — не настоящий мульти-парадигменный язык как это утверждается, впрочем как и не настоящий ООП язык ( привет классы JS ). Вот например Scala является и настоящим мультипарадигменным языком и настоящим ООП языком — там можно ( и как говорят многие даже нужно ) писать без этих statements. А в JavaScript слова мультипарадигменность и ООП были добавлены только ради красного словца и зачастую вводят людей из ФП в заблуждение.
Cake_Seller
А я вот с вами не соглашусь. Нельзя сказать что JS не OOP язык потому что в нём нет классового наследования. Прототипное наследование вполне укладывается в парадигму OOP.
Cake_Seller
Деление на ноль в JS вернет Infinity ;-)
torbasow
Верно — что тоже не сильно помогает. А вот Math.asin(2), например, NaN.
franzose
Интересно, каким образом? Это ведь явное ключевое слово для выхода из функции.
0xd34df00d
В Haskell у вас набор уравнений, формирующих граф, который редуцируется обычно через STG. В императивных языках у вас, внезапно, императивные функции.
Я давно и нежно люблю хаскель и немало на нём пишу, но на императивных языках
return
выглядит вполне себе естественным, как по мне.grossws
В императивных языках вполне можно жить с опциональным return (scala, ruby, rust, coffeescript) при достаточной гибкости языка.
В том же coffeescript оно полубесполезно (особо нет функциональных конструкций).
В ruby куда лучше, стандартная библиотека хорошо заточена под функциональщину в ограниченном масштабе и работа с
Enumerable
без использованияeach
,map
,reduce
/inject
,all?
/any?
выглядит странной и неестественной.В scala
return
надо использовать хорошо понимая (как и большинство фич, язык с приличным порогом вхождения). Например,return
из лямбды вытекает во внешнюю функцию (пример со stackoverflow):Но учитывая наличие pattern matching, того, что
if
является выражением (expression) и прочих радостей return в scala нужен не очень часто.В rust всё более-менее прилично и return стоит использовать только при явном раннем выходе из функции. Но, в отличии от scala, я не припомню, чтобы он давал такие неочевидные побочные эффекты. С учетом наличия pattern matching, того, что почти всё выражение (expression) —
return
нужен не очень часто. В той же обработке ошибок он раньше был спрятан за макросомtry!
, а сейчас за его сокращением?
. В последней версии пошли ещё дальше иloop
(бесконечный цикл; очевидно, без условия) тоже может являться выражением, если использоватьbreak some_result
.Больше всего в таком плане раздражает java 1.8: return обязателен в функциях и "многострочных" лямбдах (т. е. вида
(x) -> { return 42; }
), но запрещён в однострочных лямбдах (вида(x) -> 42
). Несмотря на то, что IDE умеют превращать однострочную лямбду в многострочную и наоборот (если она состоит из одного return statement, ессно), это несколько раздражает.x67
А как вообще функция должна понять, что ей возвращать?
В разных языках это может делаться по разному — где-то функции (или переменной с названием функции) присваивается конечное значение, где-то return, но по сути это те же яйца только в профиль.
YemSalat
Ваша проблема в том что вы зависли в парадигме «функция обязана возвращать что-то определенное», в JavaScript'e — не обязана (аргумент про «не изучил, но критикую»)
Lofer
Нюанс в том, что все функции всегда что-то возвращают, но это будет void (С++) или undefined в случае с js.
Некоторые языки программирования такие функции/Function именуют процедурами/Sub и/или предотвращают такие проблемы и вопросы с неоднозначностью поведения еще на этапе компиляции в отличие от «оно само сделает» в случае в JS.
0xd34df00d
Это лишь значит, что JS — недостаточно формально корректно спроектированный язык. Функции, которые ничего не возвращают, нельзя вызвать из некоторых математических соображений.
У void в C++ с этим есть тоже определённые проблемы (тип очевидно населён, но создать переменную этого типа нельзя), которые иногда даже в реальной жизни больно бьют во время всяких шаблонных выкрутасов.
zirix
В java нельзя получить undefined из-за забытого return. Ваш код не скомпилируется:
Error:(41, 5) java: missing return statement
Eldhenn
return не плох, он коварен. В том смысле, что он обязателен — функция не возвращает значение последнего выражения.
AndreyRubankov
Так это не в return дело, а в том что девелопер привык писать на языке, который не использует return.
Если девелопер начинал обучение с более низкоуровневых языков Pascal/C/C++/C#/etc. то ему будет напротив непривычно, что return не используется.
return коварен в Scala, где он при определенных условиях может сделать больше, чем ожидается. Но в JS он ведет себя как в большинстве C-подобных языков.
vilgeforce
Я вот писал на JS после многих лет C/C++ и даже Питона и никаких проблем с return и скобочками не испытывал вообще!
Apx
Что же такого коварного описано в документации для JS про return? Или точнее «не написано».
AndreyRubankov
Но язык и платформа невероятно быстро развиваются. И большим недостатком этого развития является то, что «каждый тянет одеяло на себя» (на фоне этого развития можно стать SuperStar! если успеешь сделать библиотеку, которой все будут пользоваться, такую как jQuery). И теперь давно минувшие «браузерные войны» превратились в «войны фреймворков».
К тому же стоит смотреть на историю развития: сначала Прототипное ООП продвигалось, как лучшее в мире, потом пришли Классы, которые невзлюбили те, что освоили прототипное, а теперь и вовсе хайп на стороне функционального js.
Ах, еще JSX появился, который позволяет писать на js внутри html пока пишешь на js, который тоже не все любят.
– Это все ведет к разделению сообщества на множество мелких юзергрупп, каждая из которых проповедует свою истину и не сильно любит чужую.
ps: А хайп девелопмент очень просто объяснить. Большинство JS девелоперов выросли на фронтендах, где все делается не так просто, как на бекенде, и любая новая библиотека призванная улучшить ситуацию воспринимается на ура.
vintage
Примечательно, что до примитивного JSX был чудесный E4X, который был стандартом, поддерживался Мозиллой, Флешом и Акробатом, и который… не взлетел.
mayorovp
В то время фронтэндщики еще не свыклись с идеей о необходимости компилировать свои проекты, а firefox — не единственный браузер.
vintage
Тем не менее, сейчас бы сдуть пыль со старичка, да внедрить, но индустрия как барышня "всё, поезд ушёл, ты был классный, но я к тебе больше не вернусь, буду мучиться с новым перспективным козлом". :-) Вот и мучаются люди с огрызком в виде JSX.
mayorovp
Ну, все же E4X заменой JSX назвать трудно. Обработчики событий через E4X не поставить, сложные объекты — не передать. Все-таки, JSX по сравнению с E4X — шаг вперед.
vintage
Шаг вперёд — два шага назад :-) Добавить в E4X возможность передавать в атрибутах сложные объекты было бы не так уж сложно.
mayorovp
… и чем бы оно тогда от JSX отличалось? :-)
vintage
DOM на выходе с возможностью его произвольного процессинга (от от DOM API и E4X селекторов, до XSLT трансформаций). Нативной поддержкой без препроцессоров. Стандарт в конце концов.
mayorovp
Ну а тут — то же самое, только еще гибче (что угодно на выходе).
vintage
JSX на выходе даёт виртуальный дом. E4X — реальный. Преимуществ у первого перед вторым нет никаких.
mayorovp
JSX на выходе дает то, на что настроено
Ashot
так прототипное ООП никуда не делось – классы в JS это по сути синтаксический сахар, прототипный подход остался на месте
some_x
По моему всё по делу. Почти со всем согласен с автором, то что в 2017 году во сферы пытаются запихать однопоточный рантайм, это не нормально.
Я считаю это результат курса ан опопсение программирования. Бизнесу не хватает программистов и они прикладывают силы чтоб любой js junior мог пилить их бизнес задачи.
staticlab
Бизнесу же в конце концов надо решить задачу. Задач много, а программистов мало. С их точки зрения лучше, когда "дешёвый" js-разработчик быстренько напишет на однопоточном ЯП решение без разруливания проблем с race condition, синхронизацией и т.п., чем это будет "правильно" пилить "дорогой" разработчик на той же Java. А затем на сервере или в кластере поднимут нужное количество инстансов приложения, и вот вам многопоточность.
В случае же, если бизнес решает, что лучше делать правильно и дорого, то он джавистов и нанимает.
Strain
Однопоточность не решает проблемы race condition. Вот один из самых известных исторических фактов по этому вопросу.
franzose
Только вот потом «сейчас и побыстрому» оборачивается проблемой «как это всё теперь поддерживать и допиливать».
franzose
Т.е. с самого старта проект превращается в легаси.
staticlab
Согласен, что дешёвые разработчики напишут говнокод, но с количеством потоков это слабо связано.
AndreyRubankov
Справедливости ради стоит отметить:
pnovikov
BTW, знавал людей, которые в таком окружении умудрились сделать подключение к БД синглтоном. А вы говорите...
AndreyRubankov
Я встречал, как кто-то в потоке обработки HTTP запроса создавал тред-пул для выполнения довольно тривиальных действий.
Девелопер действительно постарался, он сделал пул потоков, он хотел как лучше, но упустил из виду то, что придет 100 запросов и он создаст +200 потоков и системе станет очень плохо.
Но это по большей части исключение из правил.
grossws
В современном Java EE xml'а куда меньше, чем было во времена EJB2.1. 11 лет прошло от появление EJB3.0, где уже вовсю используются аннотации.
Вам кажется. Как только уверенный в себе разработчик начинает на каждый запрос порождать пул соединений к базе или делать что-то типа https://habrahabr.ru/post/334138/, то concurrency там в полный рост. Со всеми проблемами, происходящими от остутствия минимального понимания JMM.
mclander
Ну я тоже долго плевался от JS пока не стал на нём писать серьёзные вещи.
Как оказалось, что всё от чего я плевался либо не страшно, либо удачно засахарено в ES6/TS.
Возможно, что просто в отделе подняли зарплату не автору, а фронтеру)