Comments 79
с переходом на безопасный язык разработчик будет вынужден тратить значительно больше времени на «борьбу с компилятором» - например, для описания графовых структур данных, сложных взаимных зависимостей
Не нравится - пишите unsafe
Не хотите переписывать - не переписывайте. А вот новые имеет смысл писать на Rust вместо Си
Если писать unsafe - тогда какой смысл перехода? Но я согласен насчет новых проектов без большой базы старого кода.
Смысл Rust для меня в выразительности языка больше чем в безопасности.
make illegal states unrepresentable => DDD, Domain Modelling Made Functional, Влашин, конечные автоматы и вот это вот всё (показывая рукой вокруг)
Рынок бизнес-логики на порядки больше чем системное программирование. Если Rust начнут выбирать не потому что "нужна безопасность памяти", а потому что "хочу чтобы компилятор проверял мою доменную модель" - это совсем другой масштаб adoption.
Но фишка в том, что “хочу чтобы компилятор проверял мою доменную модель” - это может быть реализовано и на других языках программирования, на том же самом C++.
Формально можно. Но сильно не удобно. И всё равно без гарантий
Но на практике разница огромная. В Rust это идиоматично и эргономично: enum с данными, match с проверкой exhaustiveness, Result/Option в стандартной библиотеке. Весь язык построен вокруг этого. В C++ std::variant - это неуклюжий визитор, а std::optional появился в C++17 и всё равно не заставляет тебя обрабатывать пустой случай.
Разница как между “можно” и “естественно”. На Java тоже можно писать функционально, но никто не скажет что Java - функциональный язык.
Если адаптация Rust пойдёт через DDD/бизнес-логику, а не через замену C в ядре Linux - это действительно другой масштаб. Но пока этого не происходит, порог входа слишком высок для типичного бэкенд-разработчика.
Если честно, то я не понял как связаны “поверка доменной модели” и std::variant c std::optional. Под проверкой доменной модели я понимаю что-то в этом духе:
#include <concepts>
struct UserId { int value; };
struct Email { const char* value; };
template<class T>
concept UserModel = requires(T u) {
{ u.id } -> std::same_as<UserId&>;
{ u.email } -> std::same_as<Email&>;
};
struct GoodUser {
UserId id;
Email email;
};
struct BadUser {
int id;
const char* email;
};
static_assert(UserModel<GoodUser>);
static_assert(!UserModel<BadUser>);
Это проверка структурного соответствия интерфейсу, не доменной модели.
Доменное моделирование по Влашину - это когда невалидные состояния невыразимы в системе типов. Иными словами parse, don't validate. Классический пример:
Заказ может быть в состоянии "черновик", "подтверждён" или "отправлен". У каждого состояния разные данные
enum Order {
Draft { items: Vec<Item> },
Confirmed { items: Vec<Item>, payment: Payment },
Shipped { items: Vec<Item>, payment: Payment, tracking: TrackingId },
}Невозможно иметь tracking без payment. Невозможно забыть обработать одно из состояний в match. Компилятор заставляет.
Concepts проверяют форму данных (validate) ближе к моменту использования, пропуская грязь в домен.
По сути та же проблема что с runtime-валидацией, только сдвинутая на этап компиляции. Лучше чем ничего, но грязь всё равно живёт в системе как легальный тип - BadUser существует, компилируется, может быть передан куда угодно где нет concept-ограничения. Один забытый requires - и он просочился.
Согласен, в этому случае, без std::variant или std::optional не обойтись.
enum EngineeringUnitCodes : uint8_t {
// Temperature
DegreesCelsius [[=TEMPERATURE, =u8"ºC"_sym ]] = 32,
DegreesFahrenheit [[=TEMPERATURE, =u8"ºF"_sym ]] = 33,
DegreesRankine [[=TEMPERATURE, =u8"ºR"_sym ]] = 34,
Kelvin [[=TEMPERATURE, =u8"K"_sym ]] = 35,
// Pressure
Pressure_1 [[=PRESSURE, =u8"inH2O"_sym ]] = 1, // inH2O | inches of water at 68ºF / 20ºC
Pressure_2 [[=PRESSURE, =u8"inHg"_sym ]] = 2, // inHg | inches of mercury at 0ºC
...
Pressure_238 [[=PRESSURE, =u8"inH2O (4ºC)"_sym ]] = 238, // inH2O (4ºC) | inches of water at 4ºC
Pressure_239 [[=PRESSURE, =u8"mmH2O (4ºC)"_sym ]] = 239, // mmH2O (4ºC) | millimeters of water at 4ºC
// Electromagnetic Unit of Electric Potential
MilliVolts [[=ELECTRIC_POTENTIAL, =u8"mV"_sym ]] = 36,
Volts [[=ELECTRIC_POTENTIAL, =u8"V"_sym ]] = 58,
// Electrostatic Unit of Current
MilliAmperes [[=CURRENT, =u8"mA"_sym ]] = 39,
// Electromagnetic Unit of Resistance
Ohms [[=RESISTANCE, =u8"Ω"_sym ]] = 37,
KiloOhms [[=RESISTANCE, =u8"kΩ"_sym ]] = 163,
//Miscellaneous
PotentialOfHydrogen [[=MISCELLANEOUS, =u8"pH "_sym ]] = 59, // (acidity or alkalinity)
Hertz [[=FREQUENCY, =u8"Hz"_sym ]] = 38,
...
PercentLowerExplosionLevel [[=MISCELLANEOUS, =u8"%LEL"_sym]] = 161,
PartsPerBillion [[=MISCELLANEOUS, =u8"ppb"_sym ]] = 169,
};C++26 с рефлексией по круче раста местами будет.
А рефлексия + контракты - это еще круче:
#include <concepts>
#include <meta>
#include <string_view>
#include <type_traits>
template <std::integral T, T Min, T Max>
struct bounded {
using domain_safe = void;
static constexpr bounded make(T v)
pre(v >= Min)
pre(v <= Max)
{
return bounded{v};
}
constexpr T get() const noexcept { return value; }
private:
T value;
constexpr explicit bounded(T v) : value(v) {}
};
template <std::size_t MaxLen>
struct non_empty_string {
using domain_safe = void;
static constexpr non_empty_string make(std::string_view s)
pre(!s.empty())
pre(s.size() <= MaxLen)
{
return non_empty_string{s};
}
constexpr std::string_view get() const noexcept { return value; }
private:
std::string_view value;
constexpr explicit non_empty_string(std::string_view s) : value(s) {}
};
template <typename T>
consteval bool is_domain_safe_type() {
using U = std::remove_cvref_t<T>;
return std::is_enum_v<U> || requires { typename U::domain_safe; };
}
template <typename T>
consteval void audit_external_input() {
template for (constexpr auto member : std::meta::nonstatic_data_members_of(^^T)) {
using member_t = [: std::meta::type_of(member) :];
static_assert(!std::is_pointer_v<member_t>);
static_assert(!std::is_reference_v<member_t>);
static_assert(is_domain_safe_type<member_t>());
}
}
enum class user_role { user, admin };
using age_t = bounded<int, 1, 150>;
using user_name_t = non_empty_string<64>;
struct CreateUserRequest {
age_t age;
user_name_t name;
user_role role;
};
struct BadCreateUserRequest {
int age;
char* name;
user_role role;
};
consteval void run_checks() {
audit_external_input<CreateUserRequest>(); // OK
// audit_external_input<BadCreateUserRequest>(); // compile-time error
}
Занятно, конечно. На практике это решается: code review + конвенция "голые примитивы запрещены в API-структурах" решает 95% проблем.
C++ конечно развивается. Но меня пугают монстры под диваном. Написать write only code не поддерживаемый и не понятный там шансов сильно больше чем в Rust
И вообще, я не пишу для прода на этих языках, только питомцев.
C++ разрешены неявные преобразования, перегрузки операторов,C++ define= текстовая подстановка, удачи с отладкой, непонятки кто владеет памятью
Надо базу исправлять, а потом уже хитромудрие чтобы не пускать через апи примитивы. На этой базе ошибок сильно больше
Вот особенно понравилось
// C++: реальный код из Boost.Spirit
auto parser = *(char_('a') >> +lit("hello") | eps(true) - eol);
// Что делает этот код? Без документации — удачи.
// * — Kleene star? Разыменование? Умножение?
// >> — парсерная композиция? Битовый сдвиг? Вывод в поток?
// | — альтернатива? Побитовое ИЛИ?
// - — разность? Вычитание?)
Ничего страшного, напишем руками
macro_rules! engineering_units {
(
$(
$(#[$doc:meta])*
$name:ident : $category:ident, $sym:expr, $code:expr
),* $(,)?
) => {
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EngineeringUnit {
$( $(#[$doc])* $name = $code, )*
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Category {
Temperature,
Pressure,
ElectricPotential,
Current,
Resistance,
Frequency,
Miscellaneous,
}
impl EngineeringUnit {
pub const fn symbol(&self) -> &'static str {
match self {
$( Self::$name => $sym, )*
}
}
pub const fn category(&self) -> Category {
match self {
$( Self::$name => Category::$category, )*
}
}
pub const fn from_code(code: u8) -> Option<Self> {
match code {
$( $code => Some(Self::$name), )*
_ => None,
}
}
pub const fn code(&self) -> u8 {
*self as u8
}
}
};
}
engineering_units! {
// Temperature
DegreesCelsius: Temperature, "ºC", 32,
DegreesFahrenheit: Temperature, "ºF", 33,
DegreesRankine: Temperature, "ºR", 34,
Kelvin: Temperature, "K", 35,
// Pressure
#[doc = "inches of water at 68ºF / 20ºC"]
InchesOfWater68F: Pressure, "inH₂O", 1,
#[doc = "inches of mercury at 0ºC"]
InchesOfMercury0C: Pressure, "inHg", 2,
#[doc = "inches of water at 4ºC"]
InchesOfWater4C: Pressure, "inH₂O (4ºC)", 238,
#[doc = "millimeters of water at 4ºC"]
MillimetersOfWater4C: Pressure, "mmH₂O (4ºC)", 239,
// Electric Potential
MilliVolts: ElectricPotential, "mV", 36,
Volts: ElectricPotential, "V", 58,
// Current
MilliAmperes: Current, "mA", 39,
// Resistance
Ohms: Resistance, "Ω", 37,
KiloOhms: Resistance, "kΩ", 163,
// Miscellaneous
#[doc = "acidity or alkalinity"]
PotentialOfHydrogen: Miscellaneous, "pH", 59,
// Frequency
Hertz: Frequency, "Hz", 38,
// Miscellaneous
PercentLowerExplosionLevel: Miscellaneous, "%LEL", 161,
PartsPerBillion: Miscellaneous, "ppb", 169,
}Паритет
Что будешь делать если лайфтаймы не согласованы?
О каком пороге входа и "хочу чтобы меня компилятор останавливал" речь если всё что делает типичный бэкенд разработчик это пишет запрос ИИ агенту приписывая "без ошибок пожалуйста"
Rust часто выбирают потому, что это тупо практично. Это хорошо видно в областях, где нужно быстро выкатить продукт высокой ответственности (финансы, крипта, скоростной трейдинг) – там в последние годы практически безальтернативен Rust в качестве языка нового проекта.
Смысл перехода на Rust именно в том, чтобы писать unsafe (там, где это надо) ☺. В C++ не надо писать unsafe только потому, что вся программа от начала до конца unsafe.
Тем, что кому не нравятся, перепишут ваш unsafe на safe и для этого им не понадобится держать в голове весь проект. Веник лучше ломается по тростиночке.
наплачутся еще разрабы с растом. "слезъми изойдут". вся эта суета и движуха не просто так затеяна.
Суета и движуха - это совпадение интересов нескольких заинтересованных групп: корпорации хотят снизить затраты на безопасность, государства используют регуляторные рычаги как повод для повышения защиты инфраструктуры, (что тоже пересекается с интересами корпораций, как исполнителями госзаказа), инфобизнес монетизируют хайп, а молодые разработчики используют эту поднятую волну для карьерного роста :-)
Конспирология какая-то. Язык Rust попросту очень хороший и приятный и люди на нём пишут с удовольствием – это не приходит в голову? И кстати, «спасибо» C++; типичная история, когда опытный C++-разработчик приходит в отчаяние от того, во что превратили этот некогда великий язык, смотрит по сторонам и переходит на Rust.
Никто не спорит, что в плюсах (и в си тоже) можно придерживаться хороших практик и количество UB, расстрелов памяти и всей прочей шелухи будет меньше (чем если не придерживаться). Проблема в том, что люди не хотят придерживаться хороших практик. Они хотят писать так, как им привычнее и удобнее. И компилятор плюсов, в отличии от раста, не даёт им по рукам, когда они в очередной расстреливают память или пихают данные в одну и ту же переменную из разных потоков без синхронизации.
И вот тут уже надо решать: либо потратить пару недель на воспроизведение, поиск и исправление бага в многопоточном коде гигантской плюсовой кодовой базы (даже с использованием санитайзеров!), либо получить удар по рукам от компилятора раста сразу при разработке. Плата за последнее - это 1) учить надо новый язык с новым синтаксисом, 2) привыкать к идеологии и ограничениям раста, 3) (самое сложное для многих) принять, что ты не умнее компилятора и что когда он даёт тебе по рукам, то он в 99% прав.
И вот тут уже надо решать: либо потратить пару недель на воспроизведение, поиск и исправление бага в многопоточном коде гигантской плюсовой кодовой базы (даже с использованием санитайзеров!), либо получить удар по рукам от компилятора раста сразу при разработке. …
Это хорошо только в тории, тогда как на практике Rust не гарантирует безопасную работу в многопоточном коде, так же как и С++. Поэтому вы точно так же будете тратить те же пару недель на его воспроизведение. Собственно об этом и была изначальная статья.
Rust реально гарантирует отсутствие data races на уровне компилятора (Send/Sync traits, borrow checker). Это не то же самое что “все многопоточные баги”, но data race - самый опасный и трудновоспроизводимый класс.
Что Rust НЕ предотвращает:
deadlocks
логические race conditions (например, check-then-act)
livelock
Эти баги действительно могут стоить недель отладки и в Rust тоже.
Но утверждение “так же как и C++” - неправда. В C++ data race это undefined behavior, и ты можешь месяцами не знать что он есть. В Rust ты просто не скомпилируешь код с data race без явного unsafe.
“Так же как в С++” - это отсутствие гарантий в данной области. Конечно в C++ и Rust это реализуется по разному из-за разного подхода и общей архитектуры “по умолчанию”.
В С++ действительно сперва придется прорабатывать архитектуру и API приложения, чтобы обезопаситься от data race на уровне типов, тогда как в Rust это изначально проверяется в самом компиляторе.
Rust реально гарантирует отсутствие data races на уровне компилятора (Send/Sync traits, borrow checker). Это не то же самое что “все многопоточные баги”, но data race - самый опасный и трудновоспроизводимый класс.
Что Rust НЕ предотвращает:
1,2,3
Гарантирует, но не предотвращает, это как? =)
Borrow checker просто запрещает любой мутабельный шаринг, в тч между потоками.
Send/sync - всего лишь предупреждает о необходимости не забыть атомики и костыль для BC, чтобы хоть что то компилятор разрешил сделать .
Итого - помощи с гулькин нос. А основные проблемы не решены.
Бонусом масса неудобств.
А мемори сефети проблем в большинстве современных языков уже нет.
Borrow checker заставляет вынести мутабельный шаринг в явные, проверенные примитивы. Прикладной код остается в safe Rust и BC его полноценно проверяет. Unsafe сконцентрирован в компактных проверенных библиотеках
А мемори сефети проблем в большинстве современных языков уже нет
Это те, что с GC? Смешно.
Гарантирует, но не предотвращает, это как?
У меня впечатление, что вы придуряетесь. Перечитайте
гарантирует отсутствие data races и не предотвращает ещё 3 других указанных проблемы
У меня впечатление, что вы придуряетесь. Перечитайте
гарантирует отсутствие data races и не предотвращает ещё 3 других указанных проблемы
проблемы того же класса. Тут гарантируем, а тут рыбу заворачивали.
С мемори сефети кстати то же самое - раст гарантирует не все случаи.
В любом случае, это не проблема. Проблема в избыточной рекламе и сноскам мелким шрифтом.
Удобно - пользуйтесь, но мне неудобно.
“пишите хорошо, не пишите плохо” Не. Такие советы не работают
Они хотят писать так, как им привычнее и удобнее. И компилятор плюсов, в отличии от раста, не даёт им по рукам, когда они в очередной расстреливают память или пихают данные в одну и ту же переменную из разных потоков без синхронизации.
Это полнейшая и беспросветная чушь! Так пишут только студенты младших курсов, потому что к старшим курсам они уже вдоволь настрелялись себе в ногу и стараются всеми силами так не делать! Ошибки с памятью (как и с доступом к общим ресурсам), которые возникают в сложных проектах, появляются там не из-за безалаберности программиста, а из-за внутренней сложности архитектуры проекта. Сложность как сущность является причниной большинства проблем. И тут важно то, что эти ваши "безопасные" языки ни как не помогают уберечься от проблемы сложности. Более того, они делают сложную систему еще более сложной и запутанной.
Но хайполовый от бигтеха ухватили беса за хвост и доят тему "безопасных" языков на полную катушку втюхивая тезис о дураках программистах которые не хотят писать как надо.
Ну так часто и не хотят же. И заявляют, что так и надо ибо им мало платят и потому они могут даже немножечко вредить =)
А бывают и не могут - не умеют
Я не знаю ни одного человека который бы умышленно выполнял свою работу плохо. Есть недостаточно опытные/квалифицированные люди которые в силу отсутствия знаний или опыта могут выполнить работу не достаточно хорошо. Есть ограничения по ресурсам и времени, которые сильно влияют на качество работы (и так бывает очень часто). Но я не втречал и не слышал о работниках, которые бы специально вредили, потому что им мало платят.
Полно людей, которые говорят, что им не нужно [высшее] образование, они и так [прекрасно] могут.
Следующая категория - "нам некогда писать идеальный код" и ещё 10 причин.
Это ровно Ваше 2е и 3е утверждения =)
А в чём противоречие? Я же не спорю, что на плюсах можно обложится умными указателями, статическими анализаторами, санитайзерами, код-ревью и выстраивать правильную архитектуру: и всё будет в шоколаде. Но ровно до тех пор, пока в какой-то сторонней библиотеке, написанной пьяным студентом в бессознательном состоянии, в каких-то очень редких случаях будет вызываться delete для сырого указателя, который вы в неё передаёте из умного указателя. И тогда привет гадание по порченной памяти из коредампов)
Идея моего мнения проста: правильная архитектура и правильные методы - это хорошо, но если допускается писать неправильно и делать УБ, то в большом проекте это обязательно произойдёт незамеченно и не один раз.
Слово "безопасность" вообще достаточно далеко в настоящее время по смыслу от языков программирования, так как в существенно больше зависит от алгоритмов и контекста использования. То есть это больше про права доступа к определённой информации. В контексте языков программирования правильнее использовать слово "уязвимость" - использование огрехов в работе алгоритма/оборудования для вывода его из строя или получения неразглашаемой информации/её уничтожения. Учитывая что С++ поддерживается языковыми моделями достаточно хорошо, и разработка в целом довольно итеративное занятие, то выигрыш rust в каком-нибудь бенче "меньше уязвимостей в коде, сгенерированном одним промптом" не является сильно значимым преимуществом по моему мнению. Просто фактор личных предпочтений, эффекта "утёнка" и прочей психологии.
издержки от ошибок в ПО всегда ложатся на конечных пользователей, а не на разработчиков, поэтому у последних нет рыночного стимула к их полному устранению.
Вы описываете ситуацию с коммерческой разработкой. А ещё бывает внутрикорпоративная, когда из-за бага, уронившего прод, разработчику позвонят в 3 часа ночи. Это стимулирует.
Продукт, который активно развивается, естественным образом избавляется от старых ошибок - не потому, что кто-то целенаправленно их ищет, а потому, что переписывание улучшает его качество.
Не только улучшает, но и ухудшает. Статическая типизация, авто-тесты и borrow checker помогают бороться с добавлением новых косяков.
эта палка о двух концах, не верите проверьте, пишем приложение на ява свинг, пишем такое же на раст, иииииии где-то тут появится skills issue, в итоге если разраб понимает С++ он осознано начинает писать на плюсах, потомучто на Расте есть нюансы, но они не в тех цветах(тоесть не в той категории что типо раст плохой, или парадигмы плохие или что раст просто плохой) - суть в глубже раст показывает ошибки, понимая их, проще иногда действительно описать это на С++, чем пытаться фиксить то что нереально просто например работу модуля или библиотеки, просто потомучто в С так и разраб знает это, а раст со своими связями уже чото там другое делает и находясь в такой точке просто проще писать на С++, в этом проблема. Но и тут получается у Раста четко очерчено использование - где-то на сухом остатке это что-то либо чистое, либо библиотек или модуль чистые не текут и прочее, почему? чтобы не писать велосипеды, а сам раст прекрасен как и хаскель )
Rust не плохой, он просто честный. Он заставляет платить за безопасность временем разработчика еще на этапе написания первой строчки, а не во время отладки сегфолтов в полночь.
тоесть честность, многопоточность крутые, но есть моменты которые просто проще на С/С++, просто например потомучто библиотека не на ффи в С, а именно на С.
например, проще прокинуть бинды через модуль уже на С++23/26 уже где-то чем биться с библиотекой раста например.
Rust не плохой, он просто честный. Он заставляет платить за безопасность временем разработчика еще на этапе написания первой строчки, а не во время отладки сегфолтов в полночь.
Это еще ладно. Хуже когда падение случилось на проде. Упало не то что дорабатывали, а где-то на пару уровней ниже по стеку вызовов (и где-то даже не в продуктовом коде, а в системной API), а доступа до прода нет и воссоздавать картину приходится по дампам и джоблогам... Т.е. интуитивно понятно что кто-то где-то не туда в память залез, но визуально по коду абсолютно непонятно где именно, а на тестовой среде оно вообще не воспроизводится...
И возникают шальные мысли что все вот это проще переписать заново чем искать ошибку.
А если еще тебе намекают что цена вот этой конкретной ошибки исчисляется суммой с многими нулями чужих денег...
согласен такой момент есть, я на своём не експертном месте, столкнулся с ситуацией, взять нашу ветку, чистый код, терминал и владение,
вот на клоне майнкрафта на расте я просмотрел, что такое владение в полной мере многопоточно бесконечно, но без сети. тут GL(кусок памяти на видеокарте, шардированый алокатор на слотах, многопоточка на каналах mpsc всего цикла от генерации до отправки на карточку, со своим "сборщиком мусора по флагу dirty" )
а например в терминале, если хотеть не GL, после многопоточного владения как в игре вокселей, если сначала делаешь на canvas и Rect - просто тут по каким-то причинам уже не знаю усадка это контекста - как пишут друзья какие-то или это легитимная утечка - искать корень утечки это гемор, и решение это как раз то самое GL - честное владение! - тоесть придётся писать это владение памятью на GL, с флагом dirty тоже наверно.
и да с таким вопросом по известным причинам по терминалу не столкнулся на Java 25, в этом что-то есть, тут получилось самый бронебойный терминал, но не хватает 1мс скорости условно )
знаю что на С/С++ от ректов или контекста не течет ничего на квадратиках, поэтому модули на С++23/26 для меня как глоток свежего воздуха воспринимается как новая фича, которой хочется пользоваться )
Уже давно доказана эффективность rust, ваша заметка опоздала на лет на 5
Пруфы на доказательства будут? Или это со слов заинтересованных лиц и компаний?
гуглом пользоваться вера не позволяет? https://share.google/aimode/ZYs2872SmhtFHv5B9
Так и я могу :-)
приведи список компаний, которые уже отказались от написания кода на С++ и полностью перешли на язык rust в своей разработке. хотя бы штук 5-10 топовых
Коротко: публично подтвержденных “топовых” компаний, которые полностью отказались от C++ и целиком перевели разработку на Rust, практически нет. У крупных компаний почти всегда остается смешанный стек: C/C++ + Rust + Go + Java + Python + Swift/Kotlin и т.д.
Даже если они активно продвигают Rust, это обычно означает:
новые системные компоненты пишут на Rust,
опасные по memory safety части переписывают с C/C++ на Rust,
но не весь код компании и не полный отказ от C++.
Так что честный ответ: список из 5–10 крупных компаний с полным и публично подтвержденным отказом от C++ в пользу Rust я дать не могу, потому что таких кейсов почти нет или они не подтверждены официально.
Разве то, что они пишут новый код на Rust, и не пишут его на С++, не доказывает первоначальный тезис?
А легаси был, есть и будет. И его нет смысла переписывать с языка Х на язык Y.
Разве то, что они пишут новый код на Rust, и не пишут его на С++, не доказывает первоначальный тезис?
Нет.
… И его нет смысла переписывать с языка Х на язык Y.
Но именно этим подавляющее большинство и занимается!
Пишут выборочные части или подсистемы. Почему бы и нет.
Новые проекты полностью на Расте чтобы на слуху, не попадались.
Можно ли утверждать, что, согласно вашей статье, Rust - это заплатка со стороны разработки, призванная решить проблему плохой аналитики и архитектуры проекта?
В вашем вопросе скрыт подвох за счет использования негативной коннотации в самой формулировке. Но я все равно попробую вам ответить нейтрально.
Rust хороший проект и собственным примером показал замечательный подход к обеспечению безопасной разработки программного обеспечения. Но не в части безопасного управления памятью (где у него остаются некоторые проблемы), а в смене принципиальной парадигмы обеспечения безопасности на уровне исходного кода, когда безопасность реализуется на основе гарантий самого языка программирования.
Нет. Как раз эти проблемы Раст, как и большинство других ЯП, не решает. Это не языковые проблемы
мнение в виде краткой стати с описанием фундаментальной экономической модели разработки ПО, которая не способствует (и объективно не должно способствовать) массовому переходу с C/C++ на «безопасные» альтернативы. Так как из-за особенностей распределения затрат у разработчика ПО отсутствует экономическая мотивация
Правильный посыл, но неполные и потому делаются неверные выводы.
Ведь платить можно не только безопасностью.
Классический треугольник - время [разработки] - качество (безопасность, скорость работы) - стоимость (сложность разработки, ресурсы эксплуатации)
Итого навскидку список, вероятно тоже неполный - можно расширять
Платим памятью - и приходим к Яве или Шарпу
Платим скоростью исполнения - Питон, Руби
Платим сложностью и временем разработки - С++, Раст
Итп
Интересная идея.
В Rust работа над качеством/безопасностью кода сдвигается на более ранний этап, в прототип программы. Нет вариантов сделать MVP, не потратив время на качество кода. С этой стороны, Rust менее пригоден для продуктовой разработки, по крайней мере, на начальном этапе.
С другой стороны, код-решето даже в прототипе создаст массу проблем, и на их исправление времени уйдёт вероятно даже больше, чем было бы потрачено на борьбу с компилятором Rust. В пользу этой точки зрения можно зачесть тот факт, что Rust стабильно побеждает на ICFP Programming Contest.
Причем трудоемкость исправления ошибок, которые теоретически устраняются переходом на memory-safe языки, составляет единицы процентов от общего бюджета разработки
Что насчёт трудоёмкости поиска этих ошибок?
Rust - это лишь ещё один инструмент, не стоит его рассматривать как что-то обязательное. Бороться с компилятором - это глупая затея (в любом случае проиграешь), есть определённые "правила" написания кода, в Rust они просто более строгие, чем в других языках. Как итог из всех итераций реализации проекта должен получиться готовый продукт, который бы отвечал всем требованиям заказчика. В случае, если вы можете обеспечить это на языке(инструменте), который считается наиболее удобным и знакомым, то на нем и следует писать.
(После просмотра первых ответов с примерами на С++)
Не знаю, но лично я когда смотрю на код с наворотами на новомодных стандартах С++, то просто волосы на голове дыбом встают. И сам собой напрашивается вопрос:
На кой вам всё это?!! Вам не кажется, что "бабку пора заменить, она уже полная" (из пошлого анекдота)? :D
Из хорошего и простого низкоуровневого кросс-ассемблера aka Си за 40 с лишним лет сделали фиг знает что. НО для бизнеса он всё равно слишком сложен и опасен (и с каждым годом лишь всё сложнее и опаснее), а для системного программирования крайне избыточен и непредсказуем (здесь абсолютно согласен с Линусом Торвальдсом).
Лично я стал подозревать, что с языком что-то не так, еще когда move семантику ввели. Как бы причина была понятна, профит был ясен, но реализация в рамках синтаксиса языка уже начинала сильно напрягать, особенно когда внезапно провились всякие новые не очевидные правила сворачивания ссылок типа A&& & -> A& ; A&& && -> A&& и т.п.
Ну а современные шаблоны на C++ -это вообще мрак, особенно что касается обобщенных подходов к выделению памяти и т.п.
А по поводу Rust - не знаю. Больше похоже на какой-то очередной хайп.
IMHO Самая большая проблема как всегда - это невозможность легкого переноса legacy кода, при том, что экосистема ограничена в основном лишь системными вещами. Но спрашивается зачем кому-то переписывать уже годами работающий крайне быстрый и отлаженный код на Си?
Тем более, что были же здравые попытки начать с чистого листа с максимально возможной совместимостью по синтаксису как с Си так и с C++ - это был D.
Но и то почему-то как-то не зашло. А Rust всё же куда существеннее отличается по синтаксису и подходам. И каковы шансы, что это зайдёт?...
Ну а современные шаблоны на C++ -это вообще мрак, особенно что касается обобщенных подходов к выделению памяти и т.п.
А что не так с этим аспектом? (Кстати сходу вообще не понятно что подразумевается под “обобщенными подходами к выделению памяти”, такое ощущение, что речь идет о кастомных аллокаторах).
В том числе и эти абстракции с выделением памяти и саму неопределенность выделения памяти и критикуют системные программисты включая Торвальдса.
А лично я пишу на C++ только высоконагруженный вычислительный код отдельных библиотек. И из шаблонов использую обычно базовый минимум стандартной библиотеки типа vector и т.п.
Меня в данном случае вся эта кухня с конкретным выделением памяти не особо волнует, поскольку в моём случае всё равно это пашет процентов на 40% быстрее чем, например, на том же Object Pascal (просто в моем случае FPC не очень хорошо оптимизирует плавающую точку и не умеет так агрессивно инлайнить как VC++. Хотя и сам FPC не для интерфейса, а для очень быстрого и не прожорливого backend-а).
Но как-то несколько лет тому назад полез в шаблоны, чтобы разобраться для дела, где на самом деле что хранится, и мягко говоря офигел от тонн абстракции над абстракциями в выделении памяти. По факту просто по ассемблеру уже посмотрел и всего делов.
Поэтому, в целом наверное, могу понять, что имеет в виду Торвальдс, когда говорит, что C++ не место в системном программировании.
К слову, ни один из знакомых программистов контроллеров не использует C++ (только Си), хотя у них есть возможность писать и на C++.
Вы затронули слишком большое количество вопросов тогда как меня интересовал всего лишь один аспект – что сложного в шаблонах применительно к выделению памяти. Но из вашего ответа не понял что именно.
Или у вас “сложность шаблонов” отдельно, а “сложность выделения” памяти отдельно?
Зачем вам так "полировать"?
Лично меня тогда убила сложность понимания реального выделения памяти для шаблонных нужд при и без того излишней запутанности синтаксиса шаблонов современного С++.
Я уже не помню всех деталей, и сейчас не буду ковырять, но точно было проще понять из прохождению по асеемблерному коду в отладке.
Зачем вам так “полировать”?
Чтобы лучше понимать о чем речь.
Лично меня тогда убила сложность понимания реального выделения памяти для шаблонных нужд
Что вы под этим подразумеваете? Допустим, есть шаблонный класс:
template<typename T>
struct wrapped_value {
T _value;
};
И вы создаете экземпляр wrapped_value<double>. Про какое выделение памяти для шаблонных нужд здесь может идти речь? Выделяет ли компилятор в структуре wrapped_value<double> что-то еще кроме _value?
и без того излишней запутанности синтаксиса шаблонов современного С++
Шаблоны никогда не были запутанными, если на них не начинали извращаться (вроде type_list-ов от Александреску во времена C++98).
Шаблоны никогда не были запутанными
Это как раз когда-то на заре они не были запутанными.
А сейчас я ради интереса залез в VC++ и в одном только модуле vector насчитал 3916 строчек кода!!! О точном предназначении больше половины которых придётся только догадываться.
И Это не говоря об аллокаторах (в одном только xmemory 2624 строчки ) и т.п.
Ещё раз - если это в прикладном плане как у меня- типа выделил vector для дела и считай. Как-то работает и ладно - это одно. НО в системном программировании этому не место. Торвальдс тут прав.
А сейчас я ради интереса залез в VC++ и в одном только модуле vector насчитал 3916 строчек кода!!!
Похоже, что вы путаете языковой механизм (шаблоны) и реализацию конкретной вещи посредством этого механизма (конкретную реализацию шаблонного класса std::vector, который должен обрабатывать кучу ситуаций о которых средний разработчик даже и не думает никогда).
Соответственно, все еще непонятно о чем именно вы говорите, когда упоминаете “сложность понимания реального выделения памяти для шаблонных нужд”
НО в системном программировании этому не место. Торвальдс тут прав.
Системное программирование – это достаточно ширкое понятие, в которое входят не только ядра ОС и драйвера ОС.
Я ничего не путаю.
Я, например, могу сравнить это с текстами похожей сущности aka дженрики на других языках.
Это безусловно не вполне равнозначные понятия, но тем не менее там всё гораздо прозрачнее. И в плане выделения памяти в том числе.
Вы просто хотите топить за C++ несмотря ни на что?
Вы против того, что как синтаксис так и библиотека языка в последние лет 15 превращается в жуткую кашу, но при этом лишь усложняет и запутывает и без того не самый простой синтаксис и не самые простые подходы к разработке?.
Ну это ваша позиция.
У меня своя. Да далеко и не только у меня.
В таком виде в бизнес-приложениях и даже на производстве по хорошему ему конечно не место.
В узко системном программировании, как видим, его тоже побаиваются весьма многие.
Зато игры, обработка видео, изображений, математика и прочий высоконагруженный контент - никуда с него в ближайшее обозримое время не слезут.
Да и то - это не столько заслуга языка и библиотеки, сколько просто хороших с него компиляторов от той же MS. А так-то тот же intel fortran для чисто вычислительных задач может и более оптимальный ассемблерный код породить.
Вы просто хотите топить за C++ несмотря ни на что?
Пока что я хочу понять что скрывается за вашими словами “Ну а современные шаблоны на C++ -это вообще мрак, особенно что касается обобщенных подходов к выделению памяти и т.п.”
И единственная правдоподобная версия – незнание инструмента о котором идет речь.
Вы против того, что синтаксис языка в последние лет 15 превращается в жуткую кашу, но при этом лишь усложняет и запутывает и без того не самый простой синтаксис?
Мне нравится то, что случилось с языком в период между C++11 и C++17 стандартом (+некоторые вещи из C++20, вроде концептов и operator<=>). Но есть и то, что сильно не нравится: добавленный в C++23 deducing this и, особенно, встратый синтаксис рефлексии в C++26 во главе с оператором баян ([:e:]).
У меня своя.
Ваша позиция понятна. Непонятно есть ли за ней какие-то объективные примеры.
И единственная правдоподобная версия – незнание инструмента о котором идет речь.
Ой не надо корчить из себя всезнающего эксперта. ;)
Ибо не так давно как конкретно работают некоторые вещи в шаблонах мне даже человек писавший серьёзный код для авиамоделирования и преподававший C++ студентам не смог толком объяснить. Так же водил жалом по исходникам шаблонов и лишь делал предположения.
Но если даже вы и такой, то вас будет НУ крайне мало.
Ваша позиция понятна. Непонятно есть ли за ней какие-то объективные примеры.
Какие вам ещё примеры? Я же сказал, что использую VC++ тупо по причине того, что конечный результат dll-ки считает фильтры на 40% быстрее, чем альтернативы.
C++ я по большому счёту не использую дальше 11-го стандарта ( какие-то возможности инициализации кажется из 17-го и всё )
А когда я заканчивал университет ещё и до 11-го было далеко.
И кстати на чистом Си с массивами было бы и ещё быстрее, но с шаблонами многие вещи-то писать всё же удобнее ;)
А инженеры, которые пишут собственно под контроллеры не используют у нас C++ - только чистый Cи. И к слову, по разговорам, они с Торвальдсом абсолютно солидарны.
И если честно, то C++ как современный ООП язык - #Овно конечно полное, но вот компиляторы MS и особенно Intel ну очень хорошие...
Ой не надо корчить из себя всезнающего эксперта. ;)
Мне нужна всего лишь контретика от вас, которой почему-то нет. Знали бы вы инструмент, о котором рассуждаете, проблем с предоставлением конкретики не было бы.
Так же водил жалом по исходникам шаблонов и лишь делал предположения.
Да, да, а Карузо так себе певец, потому что вы слышали его в исполнении того же коллеги.
Какие вам ещё примеры?
Конкретные примеры, демонстрирующие “вообще мрак, особенно что касается обобщенных подходов к выделению памяти и т.п.”
Я же сказал, что использую VC++ тупо по причине того, что конечный результат dll-ки считает фильтры на 40% быстрее, чем альтернативы.
Из этого не следует, что шаблоны в C++ – это мрак, и что у “обобщенных подходов к выделению памяти” есть какие-то фатальные недостатки. Некоторые недочеты, да, встречаются. Но, имхо, вполне в пределах нормы. Особенно для языка, разрабатываемого коммитетом оторванных от реальной жизни нердов с IQ выше 170.
Знали бы вы инструмент, о котором рассуждаете, проблем с предоставлением конкретики не было бы.
Так я в отличии от вас и не корчу из себя эксперта по современным текстам библиотечных шаблонов С++.
Но только может оказаться, что ваше понимание текстов стандартной библиотеки может быть ровно таким же как у вышеупомянутого гуру по С++. Он кстати довольно известная личность в российском С++ сообществе и в ваших аналогиях к “Карузо” куда ближе.
Вообще кроме С++ я ещё использую 3 языка и среды не считая ассемблеров. И вот “удивительно”, что когда я по необходимости лезу в тексты библиотек этих языков и сред, то почему-то мне практически всё там понятно. Но вот в коде шаблонов современного С++ возникают тонны вопросов даже при прохождении в отладке.
Особенно для языка, разрабатываемого коммитетом оторванных от реальной жизни нердов
Вот именно, что создаётся полное впечатление, что и сам язык и шаблонные библиотеки для него разрабатывают не инженеры, а исключительно асоциальные и засаленные нерды, для которых важно не сделать красивую, чистую, надежную архитектуру и синтаксис, а лишь в очередной раз извратиться и выпендриться в своем засаленном кружке для таких же как они чудиков.
Ну каков язык - такие и адепты :D
Тем не менее, к выделению памяти и подобным проблемам шаблоны отношения не имеют.
Самый шаблонный ад вроде в бусте, из-за зоопарка компиляторов
Так я в отличии от вас и не корчу из себя эксперта по современным текстам библиотечных шаблонов С++.
Тут бы пруфов о том, что я как либо обозначал свой уровень знаний C++ или эксперность в понимании текстов стандартной библиотеки.
Он кстати довольно известная личность в российском С++ сообществе и в ваших аналогиях к “Карузо” куда ближе.
Я вне тусовки, поэтому мне даже конкретная фамилия ничего не скажет, не говоря уже об отсылках к неназванным экспертам.
Но вот в коде шаблонов современного С++ возникают тонны вопросов даже при прохождении в отладке.
Правильно ли я понимаю, что в качестве подтверждения своим вышевысказанным тезисам про сложность C++ных шаблонов вы предъявляете ваши личные сложности с изучением кода современных C++ных шаблонов. Типа вы заглянули в код std::vector и сразу “сложна-и-нипанятна”, поэтому-то и “вообще мрак, особенно что касается обобщенных подходов к выделению памяти и т.п.”
Все верно?
зачем кому-то переписывать уже годами работающий крайне быстрый и отлаженный код на Си?
Согласен с вами в том что всё это “перепишем на раст” это сомнительные затеи, которые в большинстве случаев плохо обоснованы (это я говорю как фанат раста). Так сказать “не трогай то что работает”. Но, почему бы не писать новые программы на расте?
Ну а на счёт хайпа - раст уже много лет на плаву, так что какая-то ценность в нём всё таки есть. Думаю он с нами останется, может быть в своей нише (по типу как Го остался).
Экономика безопасности кода или почему Rust не нужен