Pull to refresh

Comments 687

Какая-то бессмысленная истерика.
Не истерика а набор фактов и вопрос «почему всё так?» к обсуждению
В чем факт ужасности return? В том, что не нравится лично вам, не иначе.
Чем плох return, я могу предположить. Когда у функции несколько точек выхода, это не очень надёжная конструкция. Или, вот, когда return выходит не из метода, а из малозаметной стрелочной функции внутри него, это может оказаться коварной неожиданностью.
Но фигурные скобочки и точка с запятой… Тут я теряюсь.
Единственная проблема с return в JS — нельзя перенести возвращаемое на следующую строку (будет undefined если перенести).
Или, вот, когда return выходит не из метода, а из малозаметной стрелочной функции внутри него, это может оказаться коварной неожиданностью.

return такого не умеет.

function foo() {
    var f = () => {
        return 42;
    };
    f();
}

console.log(foo()); // undefined
Известно, что функция может возвращать значение только через return (а стрелочная может и без него),
и тут назревает логичный вопрос: Если в конце тела функции нету return, то в чем здесь проблема в языке или в том, кто даже основ языка не прочитал?

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

Ничего не ожидал. Я продемонстрировал что return умеет выходить из стрелочной функции.

Я изменил тот комментарий.


Было бы странно, если бы return выходил сразу из нескольких функций.

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

А зачем писать переусложненные функции?

Я не знаю зачем их пишут. Но читать их мне периодически приходится.

Ну хотя бы правильный пример для начала надо было написать. Потому что из примера нихрена оно не демонстрирует. Точнее не так: пример был о том что «если хочешь вернуть значение из функции — используй return». Стрелочная функция, как видно из названия — функция. Демо return statement то зачем?

Это (пере)упрощенный пример переусложненного метода. Тот, кто хочет выяснить почему foo() возвращает undefined, смотрит внутрь, находит return… а return-то возвращает значение не из внешней функции, а из внутренней.


Вот более жизненный пример: https://github.com/jquery/jquery/blob/731c501155ef139f53029c0e58409b80f0af3a0c/src/ajax.js#L386


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

Ничего не ожидал. Я продемонстрировал что return умеет выходить из стрелочной функции.
Как бы return выходит из той функции, которойнаписан
function foo() {
    var f = () => {
        return 42;
    };
    return f();
}

console.log(foo()); // 42


Вы ожидайте результат функции, которую не возвращаете
Ничего не ожидал. Я продемонстрировал что return умеет выходить из стрелочной функции.
Так он же не вышел!
Ваша f() отыграла как надо, просто вы ничего не возвращаете из foo()

Почему не вышел-то? Он вышел из внутренней стрелочной функции, не затронув выполнение внешней.

Прошу прощения, опечатался, имел в виду именно что он вышел, сначала из f(), а потом из foo() (только в foo он ничего не вернул).

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

Я думаю, имелось в виду "можно перепутать return из малозаметной стрелочной функцией внутри метода с return из самого метода"

Я, может, не совсем понимаю что вы подразумеваете под надежность. Но известные мне компилеры других языков не скомпилят программу, пока в каждой точке выхода не будет return. Если функция, конечно, не void func() :-)
Есть множество языков, где есть return, но его можно не использовать (php кажется, один из таких, а еще Scala) и есть множество языков, где return отсутствует как таковой (если не ошибаюсь, к ним относится Python).
Во всех этих языках результат последнего действия будет возвращен как результат функции.

есть != обязателен к использованию

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

В Python функция без return вернет None.


Такие ошбки ловятся статическим (опциональным) анализом типов, но могут доставить немало "приятных" минут.

А тут я перестал понимать, о чём речь. В Javascript никакой точки выхода без return быть не может, если это только не конец функции. Я имею в виду вот что: «модуль (в данном случае функция) должен иметь только одну точку входа и только одну точку выхода».
JS еще цветочки. А вот плюсы, они еще и объект за вас сконструируют, если вы return не напишете.

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

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

public class Foo {
    public int bar() throws Exception {
        Callable<Integer> f = () -> {
            return 42;
        };
        f.call();
    }
}

Коварный, коварный JavaS… Оу, нет, просто Java.

Я и не говорил, что Javascript хуже (или лучше Java), я просто предположил, чем может не нравиться return.

Вы поддерживаете т.з. автора о том, что return — это раздражающая особенность js


И это ещё я молчу про субъективный взгляд на раздражающие лично меня особенности типа мутабельности, фигурных скобочек, точек с запятой, return
Вовсе нет. Я высказываю предположение, что именно его может раздражать. Я не утверждаю, что return обязательно должен раздражать, мне это странно.
Это моё субъективное мнение, без очевидных объективных причин, я так и написал :)
Касаемо меня — return делает код функции более запутанным, а ещё я постоянно его забываю писать. Потому что всю жизнь писал на Erlang, Elixir, Haskell и Lisp. И от забытых return — ов много проблем, потому что функция возвращает undefined без всяких предупреждений и программа потом падает в самом неожиданном месте по какой-нибудь совсем другой причине, отловить трудно. В общем получается много бессмысленной работы.
Для меня-то как раз естественно, что если мы ничего не указываем функции возвращать, она и возвращает неопределённость. Падения по трудноотлавливаемой причине происходят не от этого, а оттого, например, что типы сами по себе втихомолку приводятся друг к другу, что там, где программист подразумевает сложение, может произойти конкатенация, а деление на ноль даст не исключение, а вполне правомерный NaN — и да, сбой в этих случаях может произойти гораздо позже, и не всегда трейс поможет.
Да, неявные преобразования усугубляют такой тип ошибки ( впрочем как и почти все типы ошибок ). Касаемо return, циклов и прочих statements — тут дело в парадигме. Видимо вы хорошо владеете императивными языками в которых есть эти statements, поэтому всё и привычно. Но в функциональных языках как правило этих statements нет, да и вообще количество statements минимально потому что всё является expression. JavaScript — не настоящий мульти-парадигменный язык как это утверждается, впрочем как и не настоящий ООП язык ( привет классы JS ). Вот например Scala является и настоящим мультипарадигменным языком и настоящим ООП языком — там можно ( и как говорят многие даже нужно ) писать без этих statements. А в JavaScript слова мультипарадигменность и ООП были добавлены только ради красного словца и зачастую вводят людей из ФП в заблуждение.
впрочем как и не настоящий ООП язык ( привет классы JS )

А я вот с вами не соглашусь. Нельзя сказать что JS не OOP язык потому что в нём нет классового наследования. Прототипное наследование вполне укладывается в парадигму OOP.
Верно — что тоже не сильно помогает. А вот Math.asin(2), например, NaN.
return делает код функции более запутанным

Интересно, каким образом? Это ведь явное ключевое слово для выхода из функции.

Касаемо меня — return делает код функции более запутанным, а ещё я постоянно его забываю писать. Потому что всю жизнь писал на Erlang, Elixir, Haskell и Lisp.

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

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

В императивных языках вполне можно жить с опциональным return (scala, ruby, rust, coffeescript) при достаточной гибкости языка.


В том же coffeescript оно полубесполезно (особо нет функциональных конструкций).


В ruby куда лучше, стандартная библиотека хорошо заточена под функциональщину в ограниченном масштабе и работа с Enumerable без использования each, map, reduce/inject, all?/any? выглядит странной и неестественной.


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


def sum(ns: Int*): Int = ns.foldLeft(0)((n, m) => n + m) // inlined add

scala> sum(33, 42, 99)
res2: Int = 174 // alright

def sumR(ns: Int*): Int = ns.foldLeft(0)((n, m) => return n + m) // inlined addR

scala> sumR(33, 42, 99)
res3: Int = 33 // um.

Но учитывая наличие 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, ессно), это несколько раздражает.

А как вообще функция должна понять, что ей возвращать?
В разных языках это может делаться по разному — где-то функции (или переменной с названием функции) присваивается конечное значение, где-то return, но по сути это те же яйца только в профиль.
Ваша проблема в том что вы зависли в парадигме «функция обязана возвращать что-то определенное», в JavaScript'e — не обязана (аргумент про «не изучил, но критикую»)
Ваша проблема в том что вы зависли в парадигме «функция обязана возвращать что-то определенное», в JavaScript'e — не обязана (аргумент про «не изучил, но критикую»)

Нюанс в том, что все функции всегда что-то возвращают, но это будет void (С++) или undefined в случае с js.
Некоторые языки программирования такие функции/Function именуют процедурами/Sub и/или предотвращают такие проблемы и вопросы с неоднозначностью поведения еще на этапе компиляции в отличие от «оно само сделает» в случае в JS.
Это лишь значит, что JS — недостаточно формально корректно спроектированный язык. Функции, которые ничего не возвращают, нельзя вызвать из некоторых математических соображений.

У void в C++ с этим есть тоже определённые проблемы (тип очевидно населён, но создать переменную этого типа нельзя), которые иногда даже в реальной жизни больно бьют во время всяких шаблонных выкрутасов.
UFO landed and left these words here
return не плох, он коварен. В том смысле, что он обязателен — функция не возвращает значение последнего выражения.
Так это не в return дело, а в том что девелопер привык писать на языке, который не использует return.
Если девелопер начинал обучение с более низкоуровневых языков Pascal/C/C++/C#/etc. то ему будет напротив непривычно, что return не используется.

return коварен в Scala, где он при определенных условиях может сделать больше, чем ожидается. Но в JS он ведет себя как в большинстве C-подобных языков.
Я вот писал на JS после многих лет C/C++ и даже Питона и никаких проблем с return и скобочками не испытывал вообще!
Что же такого коварного описано в документации для JS про return? Или точнее «не написано».
«почему всё так?»
js, как язык существует уже почти 20 лет (или больше?), но js, как полноценный язык, на котором можно писать больше, чем обработчик onclick, существует всего лет 5-7, ну а js, который уже имеет зачатки для больших проектов (ES2015) и того меньше, – ему всего 2 года.

Но язык и платформа невероятно быстро развиваются. И большим недостатком этого развития является то, что «каждый тянет одеяло на себя» (на фоне этого развития можно стать SuperStar! если успеешь сделать библиотеку, которой все будут пользоваться, такую как jQuery). И теперь давно минувшие «браузерные войны» превратились в «войны фреймворков».

К тому же стоит смотреть на историю развития: сначала Прототипное ООП продвигалось, как лучшее в мире, потом пришли Классы, которые невзлюбили те, что освоили прототипное, а теперь и вовсе хайп на стороне функционального js.
Ах, еще JSX появился, который позволяет писать на js внутри html пока пишешь на js, который тоже не все любят.

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

ps: А хайп девелопмент очень просто объяснить. Большинство JS девелоперов выросли на фронтендах, где все делается не так просто, как на бекенде, и любая новая библиотека призванная улучшить ситуацию воспринимается на ура.

Примечательно, что до примитивного JSX был чудесный E4X, который был стандартом, поддерживался Мозиллой, Флешом и Акробатом, и который… не взлетел.

В то время фронтэндщики еще не свыклись с идеей о необходимости компилировать свои проекты, а firefox — не единственный браузер.

Тем не менее, сейчас бы сдуть пыль со старичка, да внедрить, но индустрия как барышня "всё, поезд ушёл, ты был классный, но я к тебе больше не вернусь, буду мучиться с новым перспективным козлом". :-) Вот и мучаются люди с огрызком в виде JSX.

Ну, все же E4X заменой JSX назвать трудно. Обработчики событий через E4X не поставить, сложные объекты — не передать. Все-таки, JSX по сравнению с E4X — шаг вперед.

Шаг вперёд — два шага назад :-) Добавить в E4X возможность передавать в атрибутах сложные объекты было бы не так уж сложно.

… и чем бы оно тогда от JSX отличалось? :-)

DOM на выходе с возможностью его произвольного процессинга (от от DOM API и E4X селекторов, до XSLT трансформаций). Нативной поддержкой без препроцессоров. Стандарт в конце концов.

Ну а тут — то же самое, только еще гибче (что угодно на выходе).

JSX на выходе даёт виртуальный дом. E4X — реальный. Преимуществ у первого перед вторым нет никаких.

JSX на выходе дает то, на что настроено

сначала Прототипное ООП продвигалось, как лучшее в мире, потом пришли Классы

так прототипное ООП никуда не делось – классы в JS это по сути синтаксический сахар, прототипный подход остался на месте

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

Я считаю это результат курса ан опопсение программирования. Бизнесу не хватает программистов и они прикладывают силы чтоб любой js junior мог пилить их бизнес задачи.
UFO landed and left these words here
Однопоточность не решает проблемы race condition. Вот один из самых известных исторических фактов по этому вопросу.

Только вот потом «сейчас и побыстрому» оборачивается проблемой «как это всё теперь поддерживать и допиливать».

Т.е. с самого старта проект превращается в легаси.

UFO landed and left these words here
Справедливости ради стоит отметить:
  1. Хороший JS разработчик стоит столько же, сколько и хороший Java разработчик, но введу того, что JS легче изучить, туда сейчас идет очень много людей. Из-за этого специалисты начинающего и среднего уровня стоят довольно дешево.
  2. JS не на много проще, чем Java. Вернее проще в одних моментах и на много сложнее в других. Java сложнее для старта, но в сотни! раз проще для поддержки проекта, если это не уродливый JavaEE, где куча XML.
  3. Многопоточность в Java используется не часто, по крайней мере для WEB. Да, сервера сами по себе многопоточны, но каждый HTTP запрос обрабатывается в одном потоке без взаимодействия с другими. Нужно еще постараться, чтобы выстрелить себе в ногу в этом месте.
Нужно еще постараться, чтобы выстрелить себе в ногу в этом месте.

BTW, знавал людей, которые в таком окружении умудрились сделать подключение к БД синглтоном. А вы говорите...

Я встречал, как кто-то в потоке обработки HTTP запроса создавал тред-пул для выполнения довольно тривиальных действий.
Девелопер действительно постарался, он сделал пул потоков, он хотел как лучше, но упустил из виду то, что придет 100 запросов и он создаст +200 потоков и системе станет очень плохо.

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

В современном Java EE xml'а куда меньше, чем было во времена EJB2.1. 11 лет прошло от появление EJB3.0, где уже вовсю используются аннотации.


Многопоточность в Java используется не часто, по крайней мере для WEB. Да, сервера сами по себе многопоточны, но каждый HTTP запрос обрабатывается в одном потоке без взаимодействия с другими. Нужно еще постараться, чтобы выстрелить себе в ногу в этом месте.

Вам кажется. Как только уверенный в себе разработчик начинает на каждый запрос порождать пул соединений к базе или делать что-то типа https://habrahabr.ru/post/334138/, то concurrency там в полный рост. Со всеми проблемами, происходящими от остутствия минимального понимания JMM.

Ну я тоже долго плевался от JS пока не стал на нём писать серьёзные вещи.

Как оказалось, что всё от чего я плевался либо не страшно, либо удачно засахарено в ES6/TS.

Возможно, что просто в отделе подняли зарплату не автору, а фронтеру)
Может быть я не очень хороший программист, но JS я люблю. Однако считаю синдромом мечтать о том, чтобы всё было на JS.
CodeViking
Может быть я не очень хороший программист, но JS я люблю.
Многие любят JS — И это нормально.

Ненормально и странно, когда кто-то пишет — «Я люблю С++» или «Я без ума от PHP» или «Ничего нет лучше Python»

У уж если кто напишет — "Я люблю SQL" — его в дурку сразу определят.

Только про JavaScript вполне нормально сказать — "Я люблю JavaScript."

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

Имхо, конечно, имхо. (С)

Почему ненормально? Я вот много лет писал на ЖС и сейчас пишу, мне нравится множество вещей на нем, но вот люблю C#, потому что мне нравятся эмоции, которые я испытываю, когда программирую на нем. Может вы ремесленник и относитесь к программированию исключительно как к монотонной скучной работе, но не все такие.
Я вот сейчас еще на Go много пишу, но совсем его не люблю, потому что очень неудобный язык. Так что да, под решение задачи подходит и даже больше C#, но люблю я все-равно C#, к JS я нейтрален, а Go не люблю. Что тут не так?
но вот люблю C#, потому что мне нравятся эмоции, которые я испытываю, когда программирую на нем.


Ну какие могут быть эмоции в этой Microsoft инкарнации Java? Какие? — Не шутите так. Время Java и С# (с эмоциями, с эмоциями) осталось в конце прошлого века.

Когда такие гиганты как Facebook, Google, Microsoft и Twitter методично вливают многомиллионные потоки кровавых долларов в JavaScript инфраструктуру


А зачем же они это делают? Почему не вливают в кошерные языки?
Могу предположить что использование JS фреймворков от фейсбука внутри самого фейсбука выглядит не так уж и страшно — из за высокого уровня культуры разработки, 100% покрытие юнит-тестами от и до. То есть они пишут инструмент для себя. Также возможно дело в средней цене за единицу времени js разработки / низком пороге входа — дешевле взять js джуна которых много, при необходимости обучить написанию тестов и дать ему таск чтобы он писал тесты и облазил в дебаггере код вдоль и поперёк пока всё не заработает как надо чем искать Scala / Java / Erlang / Elixir / Haskell / какого-то ещё разработчика.
Могу предположить что использование JS фреймворков от фейсбука внутри самого фейсбука выглядит не так уж и страшно — из за высокого уровня культуры разработки, 100% покрытие юнит-тестами от и до.

Ну по идее ничто не мешает делать то-же самое на бэкенде и со строгими языками, зачем-же cвязывться с js?
Также возможно дело в средней цене за единицу времени js разработки / низком пороге входа — дешевле взять js джуна которых много

Вот это может быть более похоже на правду.

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

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

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

А я бы доверил, потому что знать, почему 0 == '0' для фронтэндера важнее, чем знать, почему для применения того, чтобы дети с float: left не вылетали из родителя родителю нужно какие-то бордеры невидимые делать или ещё хлеще, почему при opacity !== 1 прекращает свою работу z-index.


Просто приведения типов можно объяснить, даже this можно знать на что будет ссылаться, а вот почему z-index перестал работать вы никогда не объясните, или почему нужен position: relative там, где есть какие-нибудь вещи. Там это аксиомы, а у нас хотя бы можно как-то объяснить и предсказать поведение, хотя в некоторых очень узких местах даже в js нельзя понять какого чёрта с приведением творится.

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

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

Я говорю даже не о "красивостях" и анимациях. Даже простое знание селекторов и манипуляции с атрибутами могут избавить вас от огромного количества лишнего кода в JS и ненужной логики в компонентах. А это прямая зависимость с качеством кода и скоростью разработки. Остальное — также, так или иначе, позволяет оптимизировать рендер и делать многие задачи на более высоком уровне. Как следствие — CSS — становится органичной частью кода приложения, вы должны его полностью контролировать чтобы получать наиболее предсказуемый и качественный результат. А зная современные возможности веб-платформы верстать становится совсем не сложно и местами очень даже приятно. А использование какой-либо консистентной экосистемы UI-компонентов избавит вас от рутины. Но такой подход, конечно, более актуален в продуктовой разработке а не проектной (когда лендинги).

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

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

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

ответы на которые всё чаще сводятся «поставь родителю position: relative».


Как вы можете претендовать на фронтенд разработку? -_-

Вот как-то вот так) Я же говорю, знакомый есть, который эти нелогичности объясняет как "ну вот так вот получилось, это нужно запомнить, чинится это вот так".

претендовать на фронтенд разработку

Да запросто, если пишешь невизуальную часть фронтенда.

я сам по себе как js разработчик знать не должен


Если вы позиционируете себя исключительно как js-разработчика, то разумеется не должны. Однако, если же вы имеете смелость называть себя фронтенд-разработчиком, то как минимум обязаны.

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

Во общем — Вы правы. Но когда пишешь толстый клиент, лучше чтобы за багами z-index-ов следил отдельный человек.

Я не говорил, что не знаю CSS. Я говорил только что отдаю эту работу отдельному верстальщику. До этого два года работал без них (их не было), теперь с удовольствием освободился от необходимости подгонять внешний вид интерфейса под картинку нарисованную дизайнером — объясняю верстальщику, по какому принципу у меня элементам класс-неймы присвоены, и спокойно берусь за следующую задачу.

Блин. Пойду убьюсь.

Я могу верстать, но очень средненько и очень медленно. Если из рук проф дизайнера/верстака выходит красивое приложение, а мне этого не дано…

Приходится довольствоваться тем что из моих рук удобное и быстрое. Ну и более менее хорошо организованное.

И, что странно, при этом з/п среднего фронт-сеньора сильно выше з/п отличнийшего верстака.

А с тем что джуньоры на JS нафиг не нужны, а сеньоров рвут на лоскуты… знаком не понаслышке. На самом деле порог входа довольно таки дорогой. Только это не видно со стороны. Да, как автар статьи намекал, действительно из фронт-проекта сделать помойку легче лёгкого. Поэтому требуются очень люди с бэкграундом. Чтобы и подводные камни знали и по фен-шую работали.
Верстальщики, как и JS девелоперы, это же подмножество фронтедщиков или нет?
т.к. Фронтэнд — это все, что связано с клиентской частью приложения, с отображением.

но если в общем это уже зависит от того, какие требования к фронтендщику предьявляют в какой-то конкретной компании, в более крупных — разделяют на 2 должности, в более мелких — это один человек.
я уже так давно не видел верстальщиков, если честно.
обычно из того, что видел это дело распиливают между собой дизайнер и чувак, который что-то пилит на angular/react/vue etc.
я и сам не люблю, да и скажу честно, плохо довольно работаю с этими CSS и HTML… но как-то никому в голову не приходит верстальщика брать еще. серьезно, думал они «вымерли» уже :D

Они не вымерли, и не вымрут, пока не появятся бесплатные нормальные генераторы лендингов, а они именно с этими 2 качествами не появятся никогда.

UFO landed and left these words here
Тащить на backend интерпретируемые языки, а еще и без типизации — маразм. Только компилируемые и со строгой, желательно именной, типизацией (Golang или Rust, конечно же).
На клиенте же всё наоборот — нужна полная кроссплатформенность, а теперь и кроссдевайсность. Современные SPA фреймворки позволяют один такой bundle запустить на любом устройстве с экраном.
Но не на backend, ни в коем случае.
Пишу этот коммент только для того, чтобы выудить умные противоположные мысли из комментов к нему, если они будут.
Трудности и радости секса в невесомости сильно преувеличены (с) А. Кларк (или А. Азимов, в общем кто-то из них)

За три месяца работы на TS был только один случай, когда типизация могла бы сэкономить мне время на отладку (бага поймалась в редакторе). В остальном мне больше нравится ES6, чем TS. Но правда у меня школа Perl, который позволяет ещё больше чем JS и спрашивает потом больно, неожиданно и на продакшене, если где что прощёлкал.

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

Говорят, что v8 компилирует js в нативный код, думаете врут?
Судя по бенчмаркам, скорее всего, врут.
А в конечном счете, все выполняется на вполне себе нативном ядре процессора с его микрокодом. Так что не врут.

Вопрос в другом, какие assumptions сделает компилятор, пока будет превращать JS в нативный код? Статическая типизация в этом смысле поможет избежать ложных assumptions и четче декларировать намерения. Но ее нет :-)
UFO landed and left these words here
Языки с типизацией — унылое старьё. ))))
Похоже, не только Вы не заметили, что я не разделял статически типизированные языки от динамически типизированных.
UFO landed and left these words here

Сервер — один, труб — много. Нагрузка несоизмерима. Тем более, что сейчас каждая труба может баллистику звездолёта рассчитывать в реальном времени.

сейчас каждая труба может баллистику звездолёта рассчитывать в реальном времени

JS спешит на помощь избыткам мощности! (= Современные сайты жрут как не в себя и тормозят на десктопах, что уж о мобилках говорить.
Эм… На бэкенде «интерпретируемые языки, а еще и без типизации» чуть ли не царствуют. Весь bash/shell/cmd такой. На них не пишут бизнес-логику? Ок, тогда SQL — он тоже по факту скорее интерпретирумый, с типизацией у него «всё сложно». Кстати большинство движков SQL однопоточные (внутри запроса параллельность может быть, но следующий запрос начнется только после окончания предыдущего). Если про веб, то PHP по меркам индустрии джититься стал чуть ли не вчера. ABAP, не к ночи будет помянут, тоже, хм, элегантен, как паравоз.
А ведь это языки на которых самое мясо бизнеса зачастую крутится. Тут скорее «Golang или Rust» пока в роли белых ворон.

[Я сторонник типизированных языков, если что]
Если про веб, то PHP по меркам индустрии джититься стал чуть ли не вчера.

Я что-то упустил, и в PHP впилили JIT? Вроде только в проекте, если речь про основную ветку.
Сразу вспомнилось Wat видео от Destroy All Software.
Боль автора полностью обоснована. В последнее время я несколько увлёкся написанием ботов с MS Botframework, используя nodejs. Пока не перешёл полностью на Typescript — написание приложения больше 1000 строк, было настоящим мучением. Очень советую автору присмотреться к Typescript, как к костылю, который частично облегчает жизнь.
Благодарю! В современном мире увы каждый разработчик соприкасается с JS хочет он того или нет — больше или меньше, но это явление есть. Порой когда обсуждаю с друзьями-разработчиками какую-нибудь современную технологию кажется что находишься в клубе анонимных алкоголиков — то есть все знают что такое JS, почему он плох, но по разным причинам каждый становится замешан в этой экосистеме, иногда так и кажется что кто-то скажет

— Привет, меня зовут Олег, и я иногда пишу на JS. Нет, вы не подумайте в основном я Scala разработчик, но вот иногда приходится и в npm полазить и для grunt с webpack скрипты написать. Кстати, я не писал на JS уже 2 недели
— Давайте похлопаем Олегу

:)
меня зовут не Олег, я всеми силами пытался дистанцироваться от фронтенда, но несмотря на это мне уже приходилось писать на JS
Я бы не сказал, что Typescript костыль.
Хорошая вещь является костылём, если её предназначение — заставлять работать плохую вещь, когда её [почти] невозможно заменить.
Если бы браузеры понимали Typescript, он бы не был костылём.
Компилятор Typescript написан на… Typescript. Если я ничего не путаю, можно прикрутить компилятор к страничке и генерировать код в браузере на лету, но так никто не делает, потому что зачем.
А как прикрутить к страничке что-либо, написанное на Typescript?
Написан на typescript и скомпилирован в javascript
Что-то ребята на C++/C#/Java и тд тп всю жизнь компилируют и как-то не жалуются
Ребята компилируют в байткод, а то и в маш.коды, а не занимаются пустопорожними переливаниями между разными видами текстовых форматов.
Ну про машинный код я еще могу понять логику, это непосредственный формат для процессора. И то, сначала код переводится в ассемблер, а уже потом в машинный код, так то.
В чем же разница подачи байт кода java машины или передачи javascript кода браузеру (мог бы он принимать javascript байт код напрямую, так бы и делали) мне сложно уловить.
И то, сначала код переводится в ассемблер, а уже потом в машинный код

А до этого происходит токенизация, построение AST, линковка… Но это не имеет значения, на выходе из компилятора получаются уже готовые к исполнению модули.

В чем же разница подачи байт кода java машины или передачи javascript кода браузеру

Про Java об заклад биться не буду, но идеи там во многом аналогичны .NET CLI. Название как бы намекает: банальный текст против некоторого удобного для выполнения бинарного представления. Выгода здесь в оптимизациях, которые может провернуть компилятор (уровня модуля), удобной раскладки метаданных (стандартизированный формат, Карл! Поэтому байткод — кроссплатформенный, а в браузеры в 2к17 до сих пор шлют текстовые файлы). Да и просто байткод — это бинарное представление объектно-ориентированного ассемблера, использующий API виртуальной машины, а не сырой исходник, который еще необходимо распарсить, переварить во внутреннее представление (для конкретного движка), а потом как-то его исполнить.
Тогда это претензии конкретно к Chrome, IE, Firefox, Safari и другим браузерам.
Javascript не виноват, что разработчики браузеров не хотят принимать на запуск байткод.
Если браузеры научатся понимать некий байткод, то дни JavaScript будут сочтены, ибо он перестанет быть безальтернативен на фронте.
Был Flash, он принимал на вход байткод. Но его закопали.
Был Silverlight, он принимал байткод, — закопали.
Был JavaApplet… — закопали.

кто следущий WebAssembly?
КМК, у этих платформ было две беды: проприетарность (и как следствие — уязвимость) и отсутствие стандартизации. Как мне известно, WebAssembly этих проблем не должен иметь.
JavaApplet, как и вся джава – это стандарт, который может быть реализован разными компаниями. Но должен будет пройти сертификацию.
Flash… в целом он тоже стандартизирован и ближе к закату отдали в сообщество.
про Silverlight не могу сказать.

на счет уязвимостей. Уязвимости они не в технологии, они в имплементации, так что WebAssembly не защищен от уязвимостей.
У WebAssembly будет всего 2-3 реализации: под WebKit, под FF и под IE, т.е. от основных игроков рынка.

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

Но не был де-факто (об этом ниже).

Flash… в целом он тоже стандартизирован и ближе к закату отдали в сообщество.

Когда он стал не нужен. Звон про уязвимости слышен до сих пор.

Уязвимости они не в технологии, они в имплементации, так что WebAssembly не защищен от уязвимостей.

Браузеры тоже не защищены от этого, но от них же никто не спешит отказываться, верно?) Я к тому, что чаще всего это были самостоятельные плагины, которыми рулила какая-то компания, которая же отвечала как за возможности, так и за безопасность. WebAssembly будет ограничена API браузера, из-за чего возможности Java-апллетов и Silverlight ей будут лишь сниться, зато у пользователей проблем будет меньше.
дни JavaScript будут сочтены

Перейдём на Lua

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

Зачем? В ассемблер переводят из внутреннего представления бэкенда компилятора только если пользователь слёзно попросил. А так кодогенерация идёт сразу в бинарное представление в объектном файле.

От этого браузер не начнёт понимать js, вы просто увеличите время загрузки)
Браузер переживет. А вот время разработки и отладки уменьшится.

А клиенты с мобильным интернетом подождут, да? :)

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

Глядишь и поймут скоро без жс. с вебассембли ;-)

Typescript спасает лишь частично. Всегда можно написать as any и поломать всё. То есть если язык не бьёт вас по рукам, то это, к сожалению, не более, чем костыль

Так и в Java/C# можно все скастить к object и далее к любому требуему типу. Но зачем?

Согласен со статьёй на все 100 — с каждым словом
UFO landed and left these words here
Вычитал все каменты — условно, все проблемы решаемы — да вообще-то нет, нерешабельные — нерешабельны системно — никакой истерики не было. Как то так.
Согласен со многими фактами, приведенными в статье, но позвольте несколько замечаний и вопросов (я JS разработчик).

1. const — слышу о нём почти отовсюду. Но вот незадача — почему все думают что он должен работать точно так же как в С/С++/<вставьте любимый язык>. Я не спорю, реализация у него не лучшая, но это специфичная для языка конструкция, коротая имеет довольно простую функцию.

2. this — подобно const, крайне непонятая многими особенность языка. И опять же — использовать её необязательно.

3. Отсутствие нормальных классов/ООП. Недостаток только для людей, которые привыкли к ООП. Но соглашусь, те попытки создать ООП в JS, которые были — очень далеки от привычных многим концепций в Java/C/C++/C#/<добавьте свой язык>.

4. «Многомиллионные инвестиции кровавых денег от больших корпораций». Вы так говорите, как будто это что-то плохое. Ни один язык не станет популярным на голом энтузиазме его последователей. Нужны деньги, нужна реклама, нужна раскрутка. Как, по-вашему, работодатели узнают о языке/библиотеке/фреймворке, если он на слуху только в технических кругах?

В общем и целом, я к тому, что у всех языков есть недостатки и достоинства. У всех есть свои ниши и свои задачи. Языки — всего лишь инструменты.

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

Java тоже не сразу стала удобной. Её тоже не все готовят правильно, есть жуткий код, есть хороший.

С радостью выслушаю мнения насчет JS и его представления на уровне backend.

this — подобно const, крайне непонятая многими особенность языка

Но стоит один раз понять — и все, больше никогда этот вопрос не доставит проблем. А со стрелочными функциями использовать this стало очень приятно.

Но соглашусь, те попытки создать ООП в JS, которые были — очень далеки от привычных многим концепций в Java/C/C++/C#/

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

Жалобы поднимут дискуссии, появятся решения, новые версии, патчи и исправления.

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

Полностью согласен. Очень многие вещи усваиваются с полпинка. Как вы сказали — это уже не та жесть, которую писали 10 лет назад.


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


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

Но я думаю, что если JS не подходит для backend и он настолько плох — разработчики будут жаловаться

С чего бы это? Его в бекенд отнюдь не java/c#-гуру тащат, а вчерашние формошлепы, которые больше ничего другого не знают и знать не желают. Вот они конечно же всем довольны, а так как таких с каждым днем все больше становится, то никуда эта зараза уже не денется. Можно хоронить нормальный бэкенд, его уже не спасти.

О чем речь, эсли эта хипстота свой жабаскрипт даже на контроллеры тащит? Типичный представитель, которому лень учиться и поэтому он все хочет писать на любимом js.

Я уже молчу про десктоп, который благодаря гигантской производительности сегодня готов простить пользователю даже «электрон».
Вы знаете, после бекенда на lua/java/c++ бэкенд на node js (es7-8) сплошное удовольствие.
это первые 20 строк кода, просветление наступит позже. А луа конечно сравнивать нельзя: кошмар похлеще js
У меня сильно больше 20 строк кода, и даже больше 2000 строк, и все еще сплошное удовольствие
Если конечно быть в теме, использовать es7-8, не делать лапшу, а писать псевдосинхронный код, ну то есть понимать инструмент и правильно его использовать.

Непосредственно nginx использует lua, на этой базе построен openresty. На этой базе успешно строят производительные игровые серверы.
Lua Jit по производительности практически на одном порядке с нативным C++ кодом (ну конечно мета магия и динамическая типизация делают свое дело, но и применяя виртуальное наследование и динамический диспатчинг с хеш таблицами на C++ будет такой же результат).

Что касается парадигмы однопоточной работы. Это именно парадигма, а не какой-то там недостаток, как утверждали в ветке выше. Во первых, как в Lua, так и в JS на node нет никакой проблемы сделать мультитреды прямо из Lua\JS. И там и там прекрасно работают C++ расширения. Но смысл парадигмы в том, чтобы управляющий поток был один. Это шардинг из коробки, он принуждает вас писать приложение так, чтобы потом шардить его на самом первом уровне.
Это возможность, в конце концов, установить ряд глобальных состояний, и быть уверенным, что другой поток его не потеряет, потому что поток один. Второй поток — второе состояние, отдельное и независимое. Для общих данных же можно использовать как расширение с мультипоточностью, так и шардинг, оставаясь в пределах одного потока на процесс.
Lua Jit по производительности практически на одном порядке с нативным C++ кодом (ну конечно мета магия и динамическая типизация делают свое дело, но и применяя виртуальное наследование и динамический диспатчинг с хеш таблицами на C++ будет такой же результат).

Самый быстрый Lua хуже не более, чем на порядок самого тормозного С++?) Маркетинг такой маркетинг.
LuaJIT — один из лучших однопоточных компиляторов, смотрите пример. Но это не меняет того факта что однопоточный рантайм для высоконагруженного серверного приложения — это просто не серьёзно.
Повторюсь, включить многопоточный рантайм не проблема как в серверном Lua так и в Javascript. Но его там не включают намеренно. Полагаете, из глупости и несерьезности?
UFO landed and left these words here
Я осиливал модель с сериализацией объектов и передачей между потоков. И классическую модель, когда объект просто общий на два потока. Многие разработчики расширений под Lua и JS осиливали обе этих моделей. Их решения известны, и даже используются в ряде проектов. Но они используются тогда, и только тогда, когда разработчик знает зачем ему нужна именно многопоточность в одном процессе с общими данными. В остальных случаях он масштабирует сразу процессы, и это масштабирование можно разнести не только на ядра, но и на разные серверы.
Многопоточность с общими данными — это как бы очень специфический кейс, нужный в 0.1% задач. В остальных случаях нам важнее иметь другую многопоточность — на уровне IO, а код должен синхронно обрабатывать таски, и параллелиться по процессам.
И где же эта волшебная кнопка включения? Пример? Большинство кодовой базы js / lua / python просто перестанет работать правильно в многопоточном рантайме.
Ну, свою волшебную кнопку я дать не могу — я писал свой фреймворк для личных задач, и там кодовая база работала как в одном так и в нескольких потоках.
Не возьмусь утверждать что включение таких расширений совсем не отразится на стандартных функциях, все таки либо вы изначально пишите однопоточный псевдосинхронный код, либо сразу учитываете, или подводите кодовую базу под многопоточность, это абсолютно нормально.

Под Lua я встречал:
http://lualanes.github.io/lanes/
Под JS я глубоко не копал этот вопрос, принцип у JS и Lua в плане C++ биндингов одинаковый, и мета методы схожие, я знаю что в JS можно провернуть похожий трюк, и встречал npm пакеты утверждающие что они этот трюк проворачивают. Возможно, готовой кнопки там нет, но ее можно сделать.
Ну никто не спорит, что быстрый C\C++ код без динамических типизаций будет рвать любой язык с jit и динамической типизацией. Но это просто два уровня подхода.
Ну и в lua и node можно делать C++ расширения, если в каком-то месте нужно решить проблему производительности.
Другое дело что вам возможно просто не нравится концепция «скриптовый язык сверху, C++ снизу», а больше нравится концепт «не туда и не сюда, но все еще можно сделать снизу C++», как в Java\C#
в lua и node можно делать C++ расширения, если в каком-то месте нужно решить проблему производительности.

Node.js так воспевался возможностью писать приложения на одном языке, а тут архитектурные костыли в виде расширений на нативных языках.

Другое дело что вам возможно просто не нравится концепция «скриптовый язык сверху, C++ снизу», а больше нравится концепт «не туда и не сюда, но все еще можно сделать снизу C++», как в Java\C#

«не туда и не сюда, но все еще можно сделать снизу C++» — я бы назвал это адекватным балансом между производительностью, удобством поддержки ПО и производительностью.

Лично мне не нравится дизайн JavaScript, поэтому и удивляет рьяное желание засовывать его везде, начиная с бэкенда и заканчивая микроконтроллерами.
Я не воспеваю идею писать все на одном языке :)
Я воспеваю идею писать 90% приложения на одном языке, а 10% — на голом Си.
«не туда и не сюда, но все еще можно сделать снизу C++» — я бы назвал это адекватным балансом между производительностью, удобством поддержки ПО и производительностью.

Это же вопрос вкуса. Мне нравится, когда сверху язык совсем совсем динамический, легкий, немногословный (камень в java, но без претензий), а все что требует оптимизации, делать сразу на самом низком уровне в Си.
Вам нравится, когда сразу баланс.

Могу пояснить, откуда вообще растут корни такого подхода.
Как правило, нужно сделать 5-10 прототипов разной направленности, протестить на пользователей, понять что развивать а что нет, а потом уже делать полноценный продакшн, но не переписывать с нуля, а вертикально развивать существующий. Для этого связка JS + C подходит отлично.

Если бы мне дали энтерпрайз банкинг я бы врят-ли писал его на JS, это не его задача.
Как правило, нужно сделать 5-10 прототипов разной направленности, протестить на пользователей, понять что развивать а что нет, а потом уже делать полноценный продакшн, но не переписывать с нуля, а вертикально развивать существующий. Для этого связка JS + C подходит отлично.


Как это потом поддерживать — вопрос (мало того, что динамический язык, так еще и половина бизнес-логики ныряет в другой язык через всякие прослойки). Ну вкусовщина, ОК.
Мне хорошо и легко поддерживать, честно.
Я выбирал этот концепт не из позиции сначала легко а потом будет выкручиваться, а с позиции легко на всех этапах.
Но так то да, вкусовщина.

А есть примеры кодовой базы среднего (100k SLOC) и выше среднего (1M SLOC) размеров на JS с рассказами о поддержке такого?

Могу скопировать тройку классов из клиент-серверной игры в 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, с видом сверху.
Еще добавлю gist основного update(dt) сервера на C++. Он не дублируется на клиенте за ненадобностью, на клиент приходят постфактум физика и события, то есть на клиенте столкновения не обсчитываются.
https://gist.github.com/dmitriy-lodyanov/38cd8e42c7bef4889cdd752fc3459166
А поддержка всего этого…
Наверное также, как вы поддерживаете свои проекты. Просто держите в голове архитектуру, знаете ключевые точки, знаете где нужно добавлять объекты и расширения для новых функций. Я использую классическую модель игровых циклов, когда есть дерево объектов, каждый кадр по ним проходит обновление, во время событий срабатывают триггеры. Сервер работает на 30 fps, клиент на 60 fps. Благодаря математически корректным формулам равноускоренного движения, при разных fps на сервере и клиенте объекты все равно двигаются синхронно независимо от dt.
И даже больше 2000 строк...

На сколько порядков?

Мое сообщение именно об этом.
Не троллинга ради, но любопытства для: откуда я могу начать получать удовольствие от node.js по сравнению с C++?
JS: Пишите — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите дальше — не работает. Пишите — вдруг заработало. Вот тут вы и получаете удовольствие.
UFO landed and left these words here

Позвольте, это не так. Там скорее так: Пишите — не работает. Пишите — не работает. Пишите — о, что-то заработало! Пишите — о, ещё что-то подтянулось! Пишите — ну а теперь вообще всё тип топ.
Удовольствие приходит начиная с 3 шага.

На самом деле, удовольствие приходит с TS :)

Не соглашусь, тогда уж довайте на cloujer писать сразу, зачем нам сам js то?

Ну кложа на любителя. А зачем js, когда есть ts — сам не знаю.

Зачем ts, когда есть js, вот это я реально не понимаю.

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

Позвольте, проблемы описанные тут занесены людьми, которые изначально писали на каких-нибудь плюсах да шурупах, и пришли сюда устраивать тут свои законы. В js как писали отлично без тайпскриптов так и пишут и будут писать, потому что ретурн забыть поставить — нерадивость программиста. Решения проблемы "что же возвращает функция" — jsdoc с поддержкой в ide, которая кстати работает быстрее любых flow и тем более ts, который ещё компилировать надо. Так что нет, проблем нету, они были завезены из "забугорья", и от туда же завозят решения.

Давайте просто не будем об этом. Не охота опять начинать холивар на тему ts vs jsdoc.

Да, давайте держать типы в голове или в документации. А верифицировать их не компилятором, а пристальным взглядом. Правильно. Зачем пользоваться технологиями, когда есть человеческий мозг? :)

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

А для CI вы тоже IDE как-то разворачивать собрались?

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

Во-первых CI — не CD.


Во-вторых, проверка "сходятся ли типы" является частью тестов.


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

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

Я вот как раз написал Reinforced.Typings, держа в голове проблему, которую решает ваша дока. Если у вас есть клиент к REST-сервису, то если у того внезапно поменяется контракт и вместо объекта { Name: '...', Age: '...' } ВНЕЗАПНО владельцы сервера решат отдавать { FirstName: '...', BirthDate: '...' } — то используя TypeScript и генерацию тайпингов вы узнаете об этом еще до того как запустите приложение. В случае с голым JS — такой баг скорее всего обнаружат таргет-юзеры.

А мы прямо из MVC-контроллеров. Не хочется ради такой мелочи тащить swagger в проект

Ну у нас джависты и так сваггер-спеку отдают. А тут просто звезды сошлись, чего б не генерить с нее ts.

Как часто у вас ломаются тесты в процессе разработки? Да ладно там, лучше скажите, как часто у вас ломаются тесты в процессе рефакторинга?

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

Ломка тестов при изменении кода — достаточно частое явление. А если уж у вас 99.5% — да вы просто бог, мифическое существо. Ещё скажите, что люди, которые это тестируют вам обратно не отдают на доработку в 99%, если скажите, то я вам прямо поклонюсь.

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

На плюсах, скажем, когда пишу, при рефакторинге тесты ломаются у меня сильно чаще. А вот на хаскеле… :)

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


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

IDE способно лишь проверить, является ли код в известной мере консистентным с точки зрения типов, но не более.

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

Во-вторых, есть ли у меня способ выразить «это Int, и это Int, но это два разные по смыслу Int'а, поэтому если я вдруг начну сравнивать один с другим или вообще использовать их в одном выражении, пни меня, пожалуйста»?

Flow пробовали? Он может понять достаточно простой код, если ему расставить в нескольких местах аннотации, но к сожалению с тем же redux и connect из react-redux он уже не справляется, ему нужно в каждом месте указывать, какие типы данных ожидаются на вход колбеков.


2 по смыслу разных инта… Интересно, а в ts вы тоже каждому инту свой тип даёте, или вы всё же под 2 разных по смыслу инта делаете 2 разных по смыслу типа, которые расширяют инт, ну или не расширяют, а как-то по другому просто копируют его "интерфейс", но имеют отдельное имя типа?

Flow пробовали?

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

2 по смыслу разных инта… Интересно, а в ts вы тоже каждому инту свой тип даёте, или вы всё же под 2 разных по смыслу инта делаете 2 разных по смыслу типа, которые расширяют инт, ну или не расширяют, а как-то по другому просто копируют его «интерфейс», но имеют отдельное имя типа?

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

Я всегда страдал косноязычием, я как раз и говорил, что для разных по смыслу инта вы определите 2 разных по названию типа, чтобы компилятор вас потом по рукам бил, если ожидалось одно, а пришло другое, так вот, в jsdoc тоже есть такая конструкция как typedef, и ide будет несколько недоумевать, когда вы ей подсунете вместо функции похожей по параметрам на middleware функцию, которая ожидает 1 параметр — число и вообще возводит это число в квадрат. Но flow вообще пошлёт лесом при таких изысках, соответственно и ts должен послать.

Если я правильно понял ваш исходный тезис, то в нём говорилось о ненужности компиляторов, тайпчекеров и прочих подобных инструментов, ведь есть же IDE. Flow и TS как-то уже не очень вписываются в эту парадигму.
А если я пишу и у меня заработало с 1го раза? Я сломал систему?)))
Мои поздравления, console.log(«hello, world»)

Если у вас получается с первого раза, значит вы правильно следовали мануалу "Get Started" того фреймворка, который выбрали для работы) Дальше уже нужно будет делать уже что-то, что требует отхода от этого мануала, и тогда уже начинается именно тот цикл)

Спасибо, фреймворками не пользовался, лишь библиотечкой jQuery, просто вздумалось написать «Сапёра» на JavaScript, что-то похожее получилось, но всё время хочется «непоправимо улучшить», написать на чистом JS и как можно ближе к оригиналу.

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

Главное потом вдруг не выполнить npm i, который вам сломает проект обновлением зависимостей :-(

Не сломает вообще-то, а вот если указать неправильно версии, то да, может и сломать. Но это нужно руками сделать, само оно не сломается.

На сайте npm любой модуль нам предлагают установить так:
npm install expresshttps://www.npmjs.com/package/express

модуль будет добавлен в депенденси со следующим синтаксисом:
"express": "^4.15.4"

Смотрим документацию:
https://docs.npmjs.com/getting-started/semantic-versioning

эта запись означает что данный модуль будет обновляться при выходе минорных релизов, т.е. 4.15.4 -> 4.50.1 без проблем будет обновлен.

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

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

Обычно это всплывает у новоприбывших на проект, т.к. у них еще нету установленных модулей и модули будут выкачиваться заново.

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

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

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

Есть и более чудесные примеры. Например, разработчики Angular1 меняют API в минорных версиях, так как версии 2+ уже заняты фактически новым фреймворком с тем же именем.

А вот то, что поведение под капотом приводит к несовместимости — проблемы пакета.

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

Не гребите всех под одну гребёнку. Фармошлёпов хватает во всех языках. Сам факт появления NodeJS (как и других библиотек/движков/языков) недвузначно намекает, что не всем нравится java/C# на бэкенде. Называть людей фармошлёпами только потому что они решили попробовать что-то новое, ИМХО, несправедливо.


И опять же — никто не забирает хлеб у Java/C# — в них тоже денег вливают неплохо. За ними тоже не кто-попало стоит. У всех свои ниши и NodeJS — не серебряная пуля, как, впрочем, и Java/C#.

1. const — слышу о нём почти отовсюду. Но вот незадача — почему все думают что он должен работать точно так же как в С/С++/<вставьте любимый язык>.

Вот только const в ES2015 – работает точно так же как в C/C++/C#/Java: он запрещает изменять ссылку, но не запрещает изменять значения внутри объекта. Изменяемые объекты и коллекции будут работать одинаково – будут изменяться даже если их объявить с const (в java const назвали final, чтобы не давать ожидания, что весь объект будет неизменяемым).

С тем же NodeJS, многие его хаят за то, что он посягает на святая-святых — backend.

На самом деле NodeJs вполне подходит для некоторых задач WEB бекенда.
Тяжелые расчеты или преобразования он сделать не может в силу единого event loop и отсутствия многопоточности, но получить данные из базы или перенаправить запрос куда-то в другой сервис (то, что сейчас многие бекенды делают) – с этой задачей NodeJs справится без проблем. Единственное чего нехватает – flow types, чтобы уменьшить количество тупых ошибок.
А Автор Топика например делал 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… и есть с чем сравнивать ,-ноде это простота кода и ёмкость… сосредотачиваюсь просто на решении., а не на обрастании синтаксических лексем.
Ваше сравнение звучит как: А вы хоть раз пробовали собрать БМВ по запчастям? А вот если взять полуготовый жигули без колёс и хоп хоп колёса прикрутил и машина. Так вот БМВ — финя, а Жигули — класс.
А теперь покажите пожалуйста сравнительный код СОАП клиента на джава и на голом джаваскрипте.
Мне кажется нечестным сравнивать полуготовое решение, с голым языком. Уж хотя бы со спрингом сравнивали б…
А Автор Топика например делал soap клиент на java?(Про сервер-soap я вообще молчу)


Справедливости ради нужно сказать что мой главный промышленный язык это Erlang, с 2013 года Elixir. Формально это языки со слабыми типами, как и JS ( правда без неявных преобразований ) поэтому формально ответ — нет. На Erlang / Elixir код будет тоже более компактный по сравнению с Java. Но опять возвращаясь к слабым типам — в экосистеме Erlang / Elixir есть чудесные инструменты для статического анализа такие как Dialyzer и Xref. При правильном стиле написания кода ( тут ничего сложного нет ) эти инструменты выводят алгебраические типы для 100% функций и выражений в исходниках, буквально для каждой строчки и каждой буквы кода. То есть потенциальные проблемы с типами и просто опечатки видны ещё до запуска программы ( эти утилиты анализируют скомпилированный байткод ). В отсутствии подобных инструментов заключается один из главных минусов JS экосистемы.
TypeScript решает это для JS. Через поддержку в IDE, ещё до компиляции. Вопрос с типами снят?
Я вам еще помогу, а то по тредам либо JS, либо TS.
Есть еще замечательный Flow, у которого есть режим совместимости синтаксиса. Он анализирует JS код и дает статические проверки. Можно не покидая JS решить эту проблему.
TS — всё-таки это другой язык, не JavaScript. Да и Flow предполагает написания нотации типов для функций — необходимо их явно указывать. Это лучше чем ничего, согласен. Но есть реально классные компиляторы которые позволяют выводить типы для всех функций в программе без единой нотации типа. Вот пример простой программы на PureScript ( диалект Haskell компилируемый в JavaScript ), вот этот же код в работе. Код полностью типизированный и безопасный. Ни единой нотации типа в коде нет. Вот такая магия. В 2017 году многие компиляторы так умеют. Ещё раз спасибо за совет!
А можно поинтересоваться, где это в реальной жизни используется Erlang (который я всегда считал академическим языком, как и большинство функциональных, кроме, может быть, Lisp)?
Тут тоже не обошлось без корпораций конечно. Язык был создан компанией Ericsson в 1986 году, фирма продолжает и до сих пор вливать в него евро, недавно был релиз 20й версии. Изначально Erlang был создан под одну единственную задачу — написание ПО для маршрутизаторов ( этого же самого Ericsson ), в связи с этим там изначально отсутствовали некоторые казалось бы необходимые типы данных такие как например строки или maps, не было нормальных кастомных типов данных. Но со временем Erlang стал языком общего назначения на котором пишется почти всё что угодно. Используется по-прежнему в основном в телекоммуникациях / телефонии, очень хорош для высоконагруженных систем из-за простых и надёжных средств параллелизации ( которые кстати были ещё в первых версиях OTP середины 80х ). С приходом Elixir, платформа стала действительно популярной и на ней пишется буквально всё. Особый вклад в популяризацию Erlang / Elixir внёс фреймворк Phoenix — это новая рельса, без преувеличений.

На Erlang написан RabbitMQ, к примеру. Еще на нем был написан популярный XMPP-сервер, но название не помню.

Почему «был», он и сейчас и написан, и всё ещё жив.

на нем написан бекенд ныне крайне популярного в некоторых кругах чата Discord.

Изначально, но потом они его посадили на свои бустеры с переписью части самого ejabberd. Короче они неплохо заморочились, поэтому фб наверное таки деньги за это отвалил...

а я думал фейсбук отвалил такие деньги за количество людей которые пользуются ватсапом)

Ради одних только людей у него есть свой меседжер и вообще-то говоря нехилое количество клиентов самой соц сети.

Вы сказали
>>Справедливости ради нужно сказать что мой главный промышленный язык это Erlang, с 2013 года Elixir.
Вот я не знаю… что тут добавить… чего тогда анализируете java против node… Вот я пишу глубоко на том и на том… и могу позволить себе небольшой анализ.(Там вверху я написал где node рвёт java как тузик грелку… но у меня есть и случаи где java пользовать предпочтительнее… просто недостатки языка это продолжение достоинст)
Я Вам за 18 секунд подниму http сервер на node.

А я вам за 1,8 секунды его положу, например.
Ой да ладно положите… Вам 40 минут на java код только писать надо будет.
на bash`е все еще быстрее чем на JS
40 минут на java код только писать надо будет
Это открыть сокет и обработку сообщений по нему 40 минут писать-то?

Можно всё же вместо install использовать просто i так же как и -g вместо --global.

положить
$ npm install -g loadtest
$ loadtest [-n requests] [-c concurrency] [-k] URL
Why not python? Или рубя в который можно одной строчкой всё наговнякать?

Не стоит забывать для чего изначально делался язык и какие тогда были ограничения
UFO landed and left these words here
Да??? Прям так… Пробую скомпилить и запустить… ах блин… мне же надо либо мавен либо gradle файл сделать… так… почитаем как его делать… Ой что-то я с синтаксисом мавена не разобрался/накосячмл… сейчас погуглю.
А в node(для линукса)
yum install node(Вот даже ноду установлю для Вас)
mkdir myhttp
npm install express
 node mydir/bin/www

Можете сами попробовать
Я теперь soap клиент сделайте...websocket сделайте… файл по сокету передайте…
И сделайте это там и там… как я в соё время сделал… и офигеете как всё просто…
А древние говорили…
Упрощать сложно… а вот усложнять легко.
Я писал выше, что пишу глубоко на ноде и ява… и есть с чем сравнить… а Вы видимо только на яве.Ноде лаконичнее… легче читается… не задумываешься об всяческих лексемах.
UFO landed and left these words here
UFO landed and left these words here
Я не знаю… насчёт интуитивно-понятности Вашего кода на ноде без всякого мавена
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)
на котлине:
клиент
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)
}
Ну-ну, вы про спринг бут слышали? Все тоже делается в пару строк, но имеем нормальную типизацию. Так что не надо пудрить мозги людям.
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);
    }
}

Вы неправы. Я понимаю, что это коммент, а не статья, но то что вы демонстрируете — это скажем 10% возможностей SOAP. Поэтому у вас и получается такой короткий пример. И кстати, возьмите уже CXF — и у вас получится ровно тоже самое. И для остальных случаев, кстати.

Ещё пару лет понырять в js вам и удалите статью по собственному желанию))) (Java developer)


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


P. S. По поводу одного потока — кто запрещает ранить несколько процессов и лоудбалансить их?

Вы не совсем разобрались в теме, во первых если JavaScript был ужасен, то это было до es6 и выше. Детские болезни еще не выпилили на 100%, но встречи с ними можно избежать.
однопоточный рантайм ( в 2017 году!!! )

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

отсутствие единой системы / стандартов реализации модулей

Тем не менее вопрос решен, можно выбрать один из стандартов и в принципе все будет работать

отсутствие единых стандартов структуры проекта

Это не проблема языка, некая стандартизация есть.

слабые типы с неявными ( и порой довольно странными ) преобразованиями

Например? То что они есть, не обязывают вас их использовать, иногда разные странные вещи бывают полезны.

отсутствие нормальных классов / ООП

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

отсутствие единого вменяемого и работающего статического анализатора кода

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

этот чудесный контекст this

Лучше вообще не использовать это слово. Как goto. Это реально. Жаль, но это одна из родовых травм, кто ж в 96м году знал, что так вот оно получится.

абсолютно дурацкая реализация pattern matching

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

отсутствие единой технологии работы с асинхронным кодом

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

const ( который на самом деле НЕ const )

Не понял суть наезда. Можно наехать на var, но сегодня его и использовать моветон.

абсолютно безумный npm с пакетами качества «братишка я тебе покушать принёс»

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

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

Нет, он не идеален, но
  • Удивительно, но производительность у него не хуже чем у той же java или c# (проверял)
  • Нет заморочек с мультипоточностью, при этом асинхронность остается
  • Кроссплатформенность и обратная совместимость
  • Удобные инструменты, которые просто работают, как то например упомянутый npm

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

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

Допустим делать безопасно несложно, а вот с правильностью проблема. Мультипоточное программирование на порядок сложней однопоточного и понять, где вы теряете производительность, бывает очень тяжело. То есть в теории все понятно, избегайте блокировок и синхронизаций. Пример из жизни, был у нас крутейший мультипоточный сервер, все вроде бы написано по феншую, с неблокирующим IO, immutable данными чтобы не синхронизировать между потоками и так далее, но производительность все равно не была впечатляющей. Где мы упали? В самом неожиданном месте, логер у нас, как оказалось был блокирующий (один из популярных опенсорсных на то время), то есть когда несколько потоков пишут в лог, а писали мы много и не писать не могли, только один из них это делает, остальные уходят в контекст свитч со всеми вытекающими. По сути у нас все потоки работали хуже, чем если бы у нас был один поток, потому что в этом случае у нас хотя бы не было контекст свитчей. Ну сделали мы свой логер неблокирующим, получили другую проблему, потоки работают с данными в памяти и это очень быстро, а лог то он в файл пишется, а это хоть и быстро, но как минимум в несколько тысяч раз медленней, поэтому при большой нагрузке очередь лога начинала расти, как снежный ком, получалось или надо логи дропать или тормозить всех, подождите мы за вами записывать не успеваем. В конечном итоге мы решили и эту проблему и еще несколько которые вылезли по пути. Это я к тому, что не всегда ваш код виноват в просадке производительности. В мультипоточности очень легко выпустить весь пар в свисток и не заметить этого.
Вам лучше не лезть в проектирование с такими суждениями. Как один поток спас бы вас от тормозов лога? (ах, ну да — контекст свитч бы отсутствовал — наверное помогло бы :)
Пишите на диск уйму сообщений? Кэшируем много сообщений — и пишем один блок, кэшируем много сообщение — и пишем один блок. А если каждое сообщение писать (да еще при этом каждый раз файл открывать, а записав — закрывать), то — никакая архитектура хранилища не будет справляться.
Кэшируем много сообщений — и пишем один блок, кэшируем много сообщение — и пишем один блок.

Ось и так это делает. Если, конечно, не вызывать fsync после каждого сообщения.

На уровне бизнес-логики ось этого не делает, т.к. ничего не знает о вашей бизнес логике. Ось это делает на уровне потоков.
(ах, ну да — контекст свитч бы отсутствовал — наверное помогло бы :)

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

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

И еще у меня ощущение, что вы путаете многопоточность и асинхронность.

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

Давно уже есть seq, кибана, и, самое простое — логи в базу

Это было задолго до кибан и бигдат. И это был просто пример, как можно поскользнуться на ровном месте.
UFO landed and left these words here
Только логгер не самописный, а из семейства log4, на тот момент один из популярных и использовали его не только мы. Но проблему до нас никто не видел да и мы ее далеко не сразу обнаружили.
Господа, я может что-то путаю, но в мою молодость умение писать многопоточный код, знание примитивов синхронизации и (желательно) идиоматических задач многопоточности (обедающие философы, читатель-писатель и т.д.) входило в базовый набор навыков программиста, который проверялся на собеседованиях еще до конкретных вопросов по языку/технологии. Это вроде как было общей теоретической базой, которой обучали во всех вменяемых IT-ВУЗах.

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

Касательно непосредственно вашего примера — я не думаю что
а) вся проблема была в переключениях контекста (ибо тогда бы вам пришлось поубивать изрядную долю процессов на своем сервере для оптимизации)

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

А вот как раз вменяемая многопоточная модель с shared-данными вас могла бы спасти (отдельный поток на запись логов, да). Но то ж нет. То ж надо синхронизацию писать, ведь так? :) На крайний случай — асинхронный сервер для логов и какой-нибудь rabbitmq, чтобы не было проблем с логами в случае крэша основного процесса.

Логи замечательно реализуются через wait-free алгоритмы. Не нужны тут никакие синхронизации.

Да, но что делать если в бассейн наливается больше воды, чем выливается? Когда есть блокировка, процесс который генерирует логи, ждет и новые логи не создает, хотя при этом простаивает. А если его не блокировать, пока я пишу первый лог, он мне еще 10 настрогает. Решений несколько:
  1. Выбрасывать логи если возникло переполнение (не наш вариант, нам нужны все логи, хотя кому то может и подойдет)
  2. В момент переполнения, начинать блокировку потоков, которые пишут в лог, пока все хорошо,
    будет работать быстро и без блокировок, но в случае превышения емкости, сервис начнет подлагивать (ввиду того что у нас это была штатная ситуация, этот вариант тоже отмели)
  3. Использовать спинлоки, которые тормозят процесс на время записи лога, но не делают переключение контекста (и это то, что мы выбрали, как наименьшее зло)

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


Пример реализации.

Кстати про 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 ]; // а этот?
}

Это D.


this() — конструктор.
~this() — деструктор.
this. — экземпляр класса.

Само собой многопоточность — это сложно

Так js — это отличный выход, получить высокую производительность, но без явной многопоточности.
вся проблема была в переключениях контекста

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

Не соглашусь, если вы хотите скорости и многопоточности одновременно, общие данные между потоками зло, потому что будут блокировки, их не избежать. Операции над объектами в памяти очень быстрые,
наберите в консоли браузера
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)
1 миллион сложений мой браузер сделал за 25мс. Если этот код разбить на два потока (не в js кончено, в другом языке) и добавить синхронизацию между потоками, а как без нее, я даже боюсь предположить во сколько раз возрастет время исполнения.
Универсального рецепта нет, но нужно стремиться к тому, чтобы одновременно одни и те же данные обслуживал только один поток.
асинхронный сервер для логов и какой-нибудь rabbitmq, чтобы не было проблем с логами в случае крэша основного процесса.

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

Простите, а зачем этот код вообще выполнять в 2 потока? Если вы думаете что многопоточность — это такая волшебная таблетка, которая просто все ускоряет — вы очень сильно ошибаетесь. Я подскажу: если перед операцией sum+=i вы добавите, например, скачивание картинки — то я даже боюсь предположить во сколько раз сократиться время исполнения, если это делать в 2 потока. :)


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

Очень даже добро, если правильно выстроить обращения к общим данным. Кроме того, выше вон человек заметил про что существуют механизмы неблокирующей синхронизации (wait-free), с которыми работа с общими данными становится дюже быстрее. Погуглите по слову "concurrency".


Так js — это отличный выход, получить высокую производительность, но без явной многопоточности

Я открою для вас секретик: любой асинхронный вызов в nodejs так же — вы будете смеяться — переключает контексты. Откройте исходники и почитайте — там внутри тредпул, если я правильно врубился. Так что js в данном случае — как раз плохое решение. Хорошее — это C с posix-тредами. Но, повторюсь, это только в случае если проблема действительно в переключениях контекста, во что я по-прежнему не верю. :)


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

Сомнительное утверждение. Запись в сокет не приводит к движению магнитной головки диска (если у вас обычный HDD, а не SSD).

Простите, а зачем этот код вообще выполнять в 2 потока? Если вы думаете что многопоточность — это такая волшебная таблетка, которая просто все ускоряет — вы очень сильно ошибаетесь.

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

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

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

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


Он переключает контексты, но не в основном потоке

Простите великодушно, но переключение контекста не может происходить "в потоке". Оно происходит между потоками или между процессами. Вы что-то путаете. Если я правильно понял исходники nodejs — то там все еще веселее: в рамках якобы "однопоточной" модели у вас с каждой операцией запускается (берется из тредпула, но я для простоты говорю "запускается") неопределенное количество потоков, на которых просто висят коллбеки. И это еще бОльший ад чем использование многопоточности явно — в последнем случае у вас хотя бы есть контроль над ситуацией. Для сравнения: C# использует для тех же целей I/O completion ports, которые не создают лишних потоков.


Попробуйте написать простенький клиент сервер

Потом

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

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

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

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

Второй поток надо создать, запустить, подождать, пока он выполнится, и потом сложить.

Или достаточно кинуть задачу в очередь, а фиксированный тредпул её разгребёт.

И можно не ждать, пока он выполнится, а складывать параллельно.

И вообще, я тут наваял очень тривиальный и тупой бенчмарк:
Тута
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



Меньше 8 микросекунд на запуск и останов треда, Карл!

И вот если на всю эту канитель накладных расходов будет более 12,5мс (максимальный теоретический выигрыш от параллельности)

А теперь вот мне стало интересно: откуда у вас взялось это число?

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

Насколько? Какова вероятность отсутствия прочих свободных ядер? Особенно с тредпулами? Каково матожидание профита?
А теперь вот мне стало интересно: откуда у вас взялось это число?
Как это откуда? По условию «бенчмарка» последовательная программа отработала за 25мс (принято на слово). Если её разделить на 2 половины, то в идеальном вакууме время исполнения сократится вдвое, на 12,5мс. Если накладные расходы превысят эту цифру, значит итоговая производительность не увеличилась.

Насколько? Какова вероятность отсутствия прочих свободных ядер?
А мне то откуда знать, что у вас за машина и чем ещё она загружена? Например на небольшой однопроцессорной VPS-ке вероятность отсутствия прочих свободных ядер строго равна единице, поэтому там никакие выкрутасы с многопоточностью не смогут увеличить производительность, от слова совсем.
Как это откуда? По условию «бенчмарка» последовательная программа отработала за 25мс (принято на слово). Если её разделить на 2 половины, то в идеальном вакууме время исполнения сократится вдвое, на 12,5мс.

А, я контекст потерял, прошу прощенья.

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

К счастью, накладные расходы на более чем три порядка меньше.

А мне то откуда знать, что у вас за машина и чем ещё она загружена?

Это вам про ваше окружение надо знать, а не моё :)

Не, конечно, если у вас на всех проектах однопроцессорные VPS'ки, то да, никакие многопоточности вам заведомо не нужны.
Вы правы на счет того, что все не так просто, как описал 0xd34df00d, но все не совсем так, как вы думаете.

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

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

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

Говорить, что это будет Гарантированно медленнее – это поспешные выводы.

ps: Не стоит забывать, что за популярностью JS, NodeJS и асинхронности стоит львиная доля маркетинга и на самом деле далеко не все так красиво, как рассказывают в «рекламе».

pps:
12,5мс (максимальный теоретический выигрыш от параллельности)
А можете предоставить источник? Я так полагаю, вы читали какую-то научную работу на эту тему?
Говорить, что это будет Гарантированно медленнее – это поспешные выводы.
Не согласен. Если у вас есть ровно одно свободное ядро, на котором надо выполнить 1млн операций, то как их не диспетчерезируй, быстрее они этого не выполнятся.

ps: Не стоит забывать, что за популярностью JS, NodeJS и асинхронности стоит львиная доля маркетинга и на самом деле далеко не все так красиво, как рассказывают в «рекламе».
Я и не утверждаю, что конкретно Нода более производтельна, чем что-то другое. Я даже наоборот, почти уверен, что нодовый неявный тредпул реализован не лучшим способом. Я только о том, что распараллеливание в реальных задачах на реальном железе не всегда даёт преимущество.

А можете предоставить источник?
https://habrahabr.ru/post/334760/?reply_to=10342966#comment_10342104
1 миллион сложений мой браузер сделал за 25мс. Если этот код разбить на два потока...
Не согласен. Если у вас есть ровно одно свободное ядро, на котором надо выполнить 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» – не будет работать. И это не говоря про то, что результат от запуска к запуску будет меняться, особенно в браузере, где «постороннего шума» невероятно много.

Как-то проглядел я этот ваш комментарий раньше...


Если в системе 10 потоков и каждый находится в состоянии "готов к работе" — то эта система загружена на 1000%/N (где N — число ядер). Разумеется, на такой системе все будет тормозить. И все "преимущество" многопоточных программ в таких условиях сводится к тому что они жадно отбирают ресурсы у остальных. Не уверен что это хорошо.


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


Есть закон Амдала, который позволяет расчитать примерный выигрыш от введения нескольких потоков.

Если кратко, то следствие: минимальное время выполнения задачи равно времени выполнения действий которые нельзя распаралелить.

Выше уже приводили цифру: 8 микросекунд на синхронизацию потоков. Именно такова будет последовательная часть при разделении суммирования на два потока. На фоне параллельной части (12,5мс) ее можно не учитывать.


Так что конкретно для этой задачи деление на два — работает.

Мы в вузе не изучали многопоточность ни на одном из языков, которые у нас были: C++, C#, Delphi.

Я тоже не помню, чтобы у нас упоминали многопоточное программирование, но вероятно потому, что тогда не было многоядерных процессоров и в мультипоточности не было особого смысла, все равно процессор то один.
Мы уже привыкли, но многоядерные процессоры стали быть массовыми «всего» 10 лет назад.

А кто вам сказал про процессоры, молодой человек? Вытесняющая многозадачность появилась в unix вообще-то годах в 80х. А потом перекочевало в Windows 95 для UI. Равно как и ваше преславутое переключение контекстов. И сделано оно было для того, чтобы вы могли на одном камне сорта Pentium II слушать музыку в Winamp и смотреть интернет через netscape. Вы правда не читали об этом? Это потом уже человечество дошло до многоядерных процессоров и вопросов синхронизации кластеных вычислений. У вас блин операционная система многозадачна и многопоточна независимо от того, сколько у вас камней на матери. И как оно внутри работает — надо знать хотя бы в общих чертах, чтобы более-менее эффективно писать ПО под современные операционные системы. Поэтому это преподают в нормальных ВУЗах.

Многозадачность? Да, про многозадачность в частности и операционные системы, в целом, был отдельный курс. Но при чем здесь она.
Не ходите больше в такие вузы.