Comments 56
Эта статья будет не полной без самого популярного комментария из обсуждения на Reddit:
Let me sum up.
"We're JS twinks with no real experience with backend software dev, so instead of learning a new language that's well proven on the backend like Ruby or Python, we picked a JavaScript tool with almost no track record as a backend platform. Then we realized it sucks for a huge number of backend applications! So naturally…
1) we picked yet another completely unproven, alpha quality platform… 2) that nobody else uses in production, so support is hard to come by when it breaks,… 3) with a custom syntax (even though we picked node instead of a good platform specifically to avoid learning a new syntax)… 4) AND WE REWROTE ALL OUR SHIT BECAUSE YOLO"
Whoever makes tech decisions for this team is an irresponsible, incompetent idiot who has no business being near production systems.
Присоединяюсь.
Crystal отличается высокой производительностью. Для моих задач он оказался в 2 раза быстрее Node.
Да что угодно компилируемое быстрее ноды :-)
Он использует очень мало памяти. Crystal обычно надо менее чем 5 Мб на процесс, а Node — более 200 Мб.
Ну это как приложение напишешь.
У него имеется отличная стандартная библиотека, в результате для решения типичной задачи нам понадобилось лишь 12 зависимостей, в сравнении с сотней зависимостей Node.
На D возможно хватило бы и одной — vibe.d
Код, по умолчанию, выглядит синхронным, он использует, как и Node, цикл событий, но для организации параллелизма применяются легковесные потоки (fibers), взаимодействие организовано через каналы, как у Go. Это упрощает понимание кода.
В D аналогично, более того..
До сих пор нет настоящего параллелизма (в Node его тоже нет).
В D он мало того, что есть, так ещё некоторым контролем времени компиляции. Файберы могут баланситься на воркеры. Есть и реализация каналов как в го.
Crystal статически типизирован, поэтому об ошибках можно узнать при компиляции.
D тоже, кроме того имеет мощные возможности метапрограммирования. Например, шаблоны могут транслироваться в машинные коды при компиляции.
Crystal выводит типы, в результате, его системой типов легко пользоваться, так как не приходится слишком часто использовать аннотации типов.
D тоже их выводит, но более строго. Например, не пихает алгебраические типы где ни попадя, как ниже в комментах.
Всё ещё нет поддержки Windows (меня это не беспокоит, работаю я на Mac, код разворачиваю на Linux).
А меня беспокоит, ибо работаю под виндой. И D работает и под линуксом и под виндой. И тоже умеет компилироваться через LLVM.
Нет инкрементной компиляции (это было бы очень удобно, так как сейчас, для компиляции нашей системы после внесения изменений в код, требуется около 8 секунд).
А в D она есть, из-за чего компиляция идёт очень быстро. Настолько быстро, что на нём даже скрипты писать можно с компиляцией налету.
Существует не так много хорошо поддерживаемых опенсорсных библиотек для Crystal, но здесь всё придёт в порядок, когда начнётся использование Crystal в серьёзных проектах.
D уже довольно зрелый, с богатым репозиторием библиотек и своим пакетным менеджером.
Для D есть аналог Passport.js? Пока удалось найти только https://github.com/thaven/oauth, но хотелось бы стабильную версию, больше готовых провайдеров и хоть какую-то активность в репозитории.
Там последний коммит пару месяцев назад. Дополнительных провайдеров добавить вроде не сложно.
И чем вам Node не нравится
Фактически на одном языке и фронтэнд и бэкэнд
Эти цепочки промисов тяжело тестировать, отлаживать, код получается не особенно вразумительным. Часто бывает так, что просто глядя на код тяжело понять даже то, в каком порядке выполняются задачи и подзадачи.
async/await через babel еще 2 года назад уже отлично работали
мне Crystal нравится (потому что я рубист), но вся проблема в том, что язык еще не релизнулся: могут быть баги, обратно-несовместимые изменения и прочие прелести
гарантированно будут (я надеюсь).
А если взять какую-то ruby библиотеку и тупо компильнуть кристалом — взлетит? Или там такой игривый руби-лайк синтаксис, сейчас я руби, а сейчас нет? (я не рубист, если что)
в 98% случаях не взлетит, потребует хотя бы рихтовки напильником.
Crystal просто основан на некоторых идеях из Ruby.
Но вообще это статически-типизируемый язык с type unions, редкая штука.
То есть тип Int32 — не может быть nilable, а Int32 | Nil может (другая запись — Int32?).
И это очень сильно и удобно (и да, можно Int64 | String, например, но вообще типы он сам выведет при компиляции, если явно не писать).
Нет, метод может вернуть type union Int64 | String.
При этом по факту у вас есть две автоматически созданные ветви исполнения по типу возвращаемого результата.
def iors : Int64 | String
Math.rand > 0.5 ? 5 : "s"
end
r = iors
if r.is_a?(String)
puts "wow #{r}"
end
здесь для разных типов будут созданы/скомпилированы разные ветви исполнения, так что потеря времени компиляции только на определение типа возвращаемого значения (одна проверка только один раз после получения результата, если это необходимо)
Ещё один пример — функция возщает или ответ или ошибку
Слушай (это гипотетическая идея только из теоритического интереса), а ведь можно изобрести новый колбэк хелл.
Из примера ниже
def iors : Int64 | (puts "Welcome to hell" > Nil ? String : Nil)
Math.rand > 0.5 ? 5 : "s"
end
Несложно заметить, что структура этих двух примеров очень похожа. Однако, когда отпала необходимость в промисах, общий объем кода уменьшился. При написании более крупных приложений это заметно ещё сильнее. Серверный код DuoCMS 5 состоит из примерно 15609 строк на JavaScript. Объём кода DuoCMS 6 близок к 10186 строкам. На данный момент DuoCMS 6 имеет больше возможностей, для реализации которых потребовалось на 30% меньше кода. При этом, благодаря отсутствию промисов, этот код гораздо легче читать и поддерживать.
Можно и порефакторить этот js и получим тоже — читаемый код и уменьшение кодовой базы
const router = require('express').Router();
app.get('/', (req, res) => res.send('Hello World!'));
app.post('/api/users', async (req, res) => {
const {body} = request;
if (!body) {
return res.send("no user provided")
}
await UserService.save(request.body);
res.send('user saved');
})
Скорее всего, обработка исключений происходит внутри фреймворка (как в sinatra), так что всё ок
Ну на деле Kemal, — это просто первая ласточка, сейчас есть и иные каркасы, типа https://ambercr.io
Во-вторых, да, async/await — прекрасная концепция.
А в остальном, — Crystal надежнее и удобнее в силу своей статической типизации, тут его ближайший конкурент все-таки — tsnode Golang.
Я — активный фанат кристала и мне больно смотреть, как в него приходят js'еры и рубисты и начинают буквально ср*ть в опенсорс, ни разу не используя преимущества языка. Они думают, что они всё ещё в динамическом ЯП.
Я против кемала и amber, потому что кристал самодостаточен, и можно быстро написать быстрое приложение, используя только стандартную библиотеку. Я в принципе против фреймворков.
А ещё автор забыл упомянуть макросы. Метапрограммирование есть и в кристале, и это одна из самых главных его особенностей.
Напишите статью )
В IRC/Gitter можете пообщаться на эту тему с Araq (создателем языка).
from sequtils import nil
echo sequtils.repeat('h', 15)
Не миллион, не преувеличивайте, они же фильтруются по типу первого аргумента.
Макросы на строках, без гигиены, в негомоиконном языке — это не метапрограммирование, это курам на смех.
Если вам по душе ruby-like синтаксис, то почему тогда не Elixir?
Блин, перевод же
Я думаю проблема в том что автор пытался на ноде кодить синхронно.
достаточно написать простейшую обертку для методов контроллера которые принимает промисы и ловит эксепшены, например в своего проекте на работе я бы написал так:
class UserController {
requests(router) { // router уже держит /api
router.post('/users', this.handleRequest(this.addUser))
}
addUser(req) {
// вообще у нас прикручен валидатор на запросы, но ладно уж
if (!req.body) throw new ServerError("no user provided"); // addUser исполняется в промисе, так что ошибка вывалится в catch
return UserService.save(req.body)
.then(() => 'user saved');
}
}
Они, как правило, либо были медленнее, чем Node, либо не так удобны для целей разработки.
Интересно, python медленее nodejs (если все-таки использовать асинхронность) или менее удобен?)
А так crystal наконец-то похож на язык, который как python по гибкости, только компилируется. Надо будет глянуть.
пока желательно только для инфраструктуры внутренней.
наружу раньше февраля не стоит.
Жесткого плана нет (есть карта).
Ранее была амбициозная цель к 2018 году создать Crystal 1.0, готовый к промышленной эксплуатации.
Сейчас очевидно, что для этого пока не хватает ресурсов, но к февралю мы все же получим гораздо более стабильный/удобный язык.
Мне вот не хватает только иногопоточности для некоторых применений.
CrystalПочему не Nim или Julia?
Путешествие из Node в Crystal