Comments 11
Как вы подходите к разработке высоконадёжных серверных систем?
Пишем их на Erlang. Ну и тестирование, конечно же.
Странная статья:
— высокая надежность для максимум десятков запросов секунду? Это точно проблема?
— в стресс тестировании по сути речь про то, что гоняйте ваши тесты с 'race' хотя бы перед мержем в мастер
— за греческие буквы в коде руки отрывать 'Ω := NewGomegaWithT(t)'
— как тестировать распределенную систему с неизвестной заранее топологией? Ничто от уровня unit до e2e тестов тут не поможет. А это ключевой момент для проекта из статьи
— mock != заглушка. Заглушка — это скорее 'stub'.

Статья просто про тестирование.
go и ООП в одной строчке — вгоняет меня в ступор.

чуть более полтора года пишу микросервисы на go, и вот что понял:
— низкий порог вхождения: это действительно так, ну собственно как в любом более-менее современном языке, если вы, конечно, не собираетесь писать на С/С++, Java, etc, там действительно дальше хелло-ворлда сложно пойти без изучения особенностей языка
— go прост — это иллюзия, писать качественный софт на любом, пусть самом простом языке — практика приходящая с опытом, у меня, я считаю, спустя 1.5 года, это не получается, го посволяет делать хрязные хаки для быстрого решения срочной задачи, но ничего не бывает более вечным чем временное
— go лаконичен — ну если следовать принципам го, собственно как и принципам и практикам другого языка — то да, но он позволяет писать нечитабельную хрень которая самого автора способна запутать спустя недели 2, тот-же gofmt для форматирования кода, он банально пустые строки не убирает, напиши 500 переносов — он с ними ничего не сделает…

и вообще, когда слышу оды про преимущества go, на ум приходит 4 вещи: мапинг, интерфейсы, рефлексия, слайсы… это то, что позволить сделать ваш код ужасным, нечитаемым, самому Богу трудно понятным… но программа будет работать, довольно шустро… ну максимум превышение количества открытых дескрипторов, что решается перезапуском программы…

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

func read(file string){
f,e := os.OpenFile(file, os.O_RW, 644)
}

for {
 time.Sleep(time.Milisecond)
read("some.file");
}



пример не из лучших, но заставит ОС понервничать, без явного-на-всякий-случай defer f.Close() в функции read после попытки открытия файла, дескрипторы будут накапливаться, хотя функция read была вызвана, чтото сделала, и все что она инициализировала — должно по идее исчезнуть… инициализированные переменные, и т.п., в том числе открытые дескрипторы… это же, кажется, логично…
UPD: и все же, почему я выбрал go?… да все просто, затрахал рнр, куча скриптов в проекте, хотел типизацию нормальную и т.п. (причин много, хотел компилируемый язык), но повелся на простоту и надежность языка, и чем дальше иду, тем больше вижу подводных камней в мире Го, рассматриваю ерланг, он в некоторых примерах обходит го и сам по себе достаточно симпатичный и честный :)…

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

но с другой стороны, go часто позиционируют как язык с простым созданием параллельных подпрограмм (горутин), но в erlang это вроде как цель, а не фича, кроме того во втором — есть горячая замена кода, чего нет в первом (есть способы, кто-то даже на хабре статью писал как пропатчить запущенную и скомлированную программу на го, но там асма (в примере) для патча больше чем измененного кода)…

но на erlang код выглядит лаконичнее чем на go, что опять продвигают как фичу го (лаконичность)…

попробуй разберись где истина…

Мне по небольшому знакомству с erlang показалось, что он прекрасен, чтобы написать уровень транспорта, чтобы сделать отказоустойчивую распределенную систему или из одного протокола в другой перегнать данные. Но вот "числодробилку", как я понял, на нем не стоит делать, как и рабоиать с текстами, строками.
В этом смысле go универсальнее. Да, транспорт можно лучше написать на erlang или elixir. А числодробилку — на c/c++. Но на golang и то и то можно сделать достаточно неплохо, используя один язык.


*Сам год назад начинал изучать elixir, но оставил, во многом потому что рынок elixir, erlang только угасает, а не поднимается.

Согласен с критикой Go.

Кстати, попробуйте обратить внимание на Crystal (crystal-lang.org) — компилируемый со статической типизаций и слоганом «fast as C, slick as Ruby», который подтверждается.

Мой основной язык Python, второй (был) Go. На обоих написано приличное количество работающего кода.

Я был в поиске, на что уйти для около-веб разработки (сервисы, боты, расчеты на лету) и выбрал Crystal — реально нравится. Я рассматривал и пробовал некоторые участки реализовать на Haskell, Erlang, Elixir, Scala, Kotlin, Julia, Nim, Rust, Typescript (для Node), даже Pharo смотрел.
Основная мотивация поиска языка: крайне желательная статическая типизация без боли, средние/низкие требования к ресурсам системы (собственно, поэтому не подошли по потреблению памяти и размерам JVM языки); желательно с REPL, хорошая производительность (уровня Java или лучше); желательно с поддержкой иммутабельности на уровне языка или за счет наличия удобных коллекций; конкуррентность обязательна, параллелизм не обязателен.

Могу сказать, что для меня Crystal — просто глоток свежего воздуха. Производительность разработки (код, рефакторинг, архитектурные изменения) на порядок выше чем в Go, соизмерима с Python. Когнитивная нагрузка — меньше. Язык исключительно лаконичный, он черпал вдохновение от Ruby и является полностью ОО с поддержкой нужных вещей из функционального программирования ((0..10).map{|i| puts i} — итерация по диапазону с передачей значения в блок) и очень близок (или даже ближе?) к изначальному замыслу ОО, реализованному в Smalltalk. Код компактный, типобезопасный и null-безопасный, размер бинарников без зависимостей после strip и upx для небольшого веб-сервиса 300-500КБ, для сравнения, телеграм-бот на Scala без зависимостей — 30MБ fatjar. На бенчмарках Techempower показал хорошие результаты. Есть пакетный менеджер. Изначально разрабатывался в компании, что, на мой взгляд, плюс: практическая направленность + ориентация на применение в бизнесе. Открытый и написан сам на себе. Это фронтенд для LLVM. В интернетах есть бенчмарки по сравнению производительности: все очень достойно (те же фибоначчи на уровне с C, существенно быстрее Go).

Из минусов для меня пока: версия 0.24 (типа не 1.x, но он вроде близок) и не очень сильная поддержка в IDE (есть плагин для vscode с не очень сильным автокомплитом, но это решаемо).

Попробуйте, вам понравится)

Go является языком со статической типизацией. Типы — это контракт между различными фрагментами кода, выполняющимися совместно. Без автоматической проверки типов в процессе сборки проекта, если нужно придерживаться строгих правил покрытия кода тестами, нам пришлось бы реализовывать тесты, проверяющие эти «контракты» самостоятельно. Так, например, происходит в серверных и клиентских проектах, основанных на JavaScript. Написание сложных тестов, направленных лишь на то, чтобы проверить типы, означает массу дополнительной работы, которой, в случае с Go, можно избежать.

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


тут должна быть картинка на которой гофер смотрит на interface{} и спрашивает — "Is this type safety?"

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


Но вот Gomega прикольный BDD пакет, надо попробовать.
Only those users with full accounts are able to leave comments. Log in, please.