Pull to refresh
3
0.3
Send message

Там вроде только OSD переписали — то есть собственно демон который висит над диском и шурудит секторами, по одному демону на диск, а остальное осталось как есть; да и Magic Pocket там важная, но не самая объёмная часть инфраструктуры. То есть да, в целом дело хорошее и вселяет надежду (я уже джва году жду не дождусь возможности попробовать Rust в embedded продакшне), но я не уверен, что это большая веха для Rust. Скорее просто ещё одно напоминание о том что такие вещи вообще не стоит писать на garbage collected языках.

А точно был мальчик? Потому что я тоже эту публикацию помню, а потом вроде бы оказалось что там журналистов учёные насиловали как могли, и на самом деле Dropbox переписал на Rust только пару мелких служб в которых у них затык по производительности был, а всё остальное как было на Go так и есть.

function show_author(name) {
  user = get_user(name)
  if ok?(user) {
    show(user)
  } else {
    log("Something wrong with " + user)
    show(ADMIN)
  }
}

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


// name типизировано и всё-таки компилируется - поздравляю вас гражданин соврамши.
void show_author(std::string name) {  // Строка может быть пустой.
  auto user = get_user(name);  // Проверяет name.empty().

… делаете предположение, что надо изобретать собственный тип...


// Опять типизировано и опять компилируется - дважды соврамши.
void show_author(std::optional<std::string> name) {  // Из стандартной библиотеки.

… неконсистентны в том, где вы обрабатываете ошибки; user проверили перед передачей в show() но предполагаете, что show_author() может получить аргумент без проверки; ну и наконец умалчиваете о том, что в вашем варианте вам ещё потребуется написать тест, который вам покажет что ваша нетипизированная show_author() (а заодно и get_user(), потому что контроля типов и там нет) не взрывается при передаче не только строки или Null, но и какого-то другого типа.


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

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

Похоже на то… chapuza, какие-то комментарии будут? Код в статье некорректный (а это, если что, треть всего кода в статье), хочется увидеть корректный и понять, как он иллюстрирует недостатки сильной типизации.

Я имел в виду то, что непонятно, по какой причине — как автор утверждает — не скомпилируется код с сильными типами (если автор вообще имел в виду сильные типы а не статические — я не могу додумать правильный пример за него). С сильными vs. слабыми я даже не могу придумать вариант — код выше не делает никакого преобразования типов. Если же автор имел в виду static vs. dynamic, что-то вроде name = get_user(user); if name != Null ..., подразумевая что со статическими типами мы не можем вернуть Null вместо строки и вынуждены изобретать variant type (подозреваю что это, судя по "… изобрести новый монадический тип для возможно указанного автора"), то получается уже совсем другой код, в котором get_user() сознательно написана без возможности вернуть ошибку (кодом возврата с передачей name через аргумент / пустой строкой / исключением и т.п.).

function show_author(name) {
  if get_user(name) {
    show(name)
  } else {
    log("Something wrong with " + user)
    show(ADMIN)
  }
}

Кстати, не затруднит поправить этот код? Я просто не вижу, откуда взялся user — наверное, имелось в виду show_author(user) и дальше get_user(user) вместо get_user(name)? Потому что это влияет на суть примера — ошибку-то вы вроде проверяете. :) Пример не показывает, почему код бы не скомпилировался с сильными типами.

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

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


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

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

Множественное наследование тянет за собой diamond problem, так что от него уже все шугаются. Плюс не всегда нужна семантика is-a, миксины хорошо ложатся на текущий курс партии — composition over inheritance.


Когда полезно иметь данные в миксине — например в геймдеве. Если хочется чтобы объект имел свойства 'Serializable', 'Drawable', 'InventoryOwning' и 'Killable' (и ещё много чего), то реализовывать через множественное наследование — разлапистая иерархия получается, и изменять потом сложно. Легче набрать объект из миксинов, тем более что тесное взаимодействие с основным классом будет наоборот вредить гибкости.

Меня вот что в статье удивило...


И сколько бы не говорили, что деньги — не главное, именно они являются мерилом успеха в современном обществе. Счастье на них не купишь, а вот новые возможности и определенную свободу вполне. За этим и едут. <...> Но в любом случае российские зарплаты пока не дотягивают до европейских.

Есть ли выход? <...> Как удержать ценного разработчика?

… и дальше про молодёжную политику, про повышение квалификации, про интересные задачи и работу над интересным проектом в дружной команде, про всё что угодно кроме, собственно, конкурентных зарплат. Чего вы только не придумаете, Штирлиц, чтобы не ехать на картошку. :) Давайте статью переименуем в "1001 способ удержать разработчика без повышения зарплаты".

Этим раньше занималось централизованно 22 ЦНИИ МО, мы с ним как-то работали, потом функции распределили. Но да, на закладки проверяют, и даже сами разработчики которые их применяют тоже делают проверки (скажем, ставят в безэховую камеру для проверок на посторонние ЭМ эмиссии чтобы добро от военпредов получить). Ну и списки доступных для применения комплектующих держат.

Наверное, есть исключения — или долгоиграющие AAA проекты (кхе-кхе, на тебя смотрю, Star Citizen), или всякие MMO/MOBA у которых очень долгий цикл сопровождения. Но да, для проектов поменьше, для инди, выкатить рабочее важнее внутренних красот.

Ну так это из блога Unity, понятно что там DOTS будет. :)


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

Может быть, стоит посмотреть на участок, где создаются объекты производных классов? Это не критика, я верю что вы дотошно всё рассмотрели, так что это мысли вслух; я пробовал, и неиспользованные виртуальные функции GCC с -flto удалять может, но спугнуть его может что угодно — скажем, если заключить создание объекта производного класса в if то, даже если там выше константа и можно этот if выбросить в ходе оптимизации, то всё равно откажется верить что никаких других конкретных классов из этой иерархии не создаётся.


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

Вот — у вас самих проект на 19к LoC, а говорите что не до тысяч строк. :) В моём примере это медицина была, там много всего на борту, тот же offline анализ данных.


Понятно что на C тоже можно делать очень крупные проекты для МК. Просто на C++ это быстрее писать, часто легче читать и поддерживать, и, если знать что обходить стороной, то практически забесплатно.

Embedded сильно разный везде бывает, у всех своя специфика, для каких-то орехов как раз впору. :) И мегабайт для этого тоже не нужен. Вот из своей практики пример — количество in-house кода подбирается к двадцати тысячам строк (в основном C++, немного C, немного ассемблера в узких местах), если весь библиотечный код посчитать (а библиотек там порядком) то почти полмиллиона строк кода. И это компилируется для машинки с 256к флэша (точнее 192к, остальное отведено на загрузчик с обновлением по воздуху) и 32к оперативной памяти.


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

Микроконтроллеры и задачи разные бывают, подчас на десятки и сотни тысяч строк кода счёт идёт.

А вы с -flto проверили? Или просто в статье не упомянуто? Я ещё раз с испугу перечитал, вдруг, думаю, в первый раз проглядел. :)

Information

Rating
1,758-th
Registered
Activity