сейчас уже неясно. Раньше любое переписывание проекта на новый язык — это был тупиковый путь. Но с использованием ИИ подобные задачи должны решаться проще. В любом случае пусть попробуют. 1 человек — не такие большие затраты.
Вера это не наш удел. Но вероятность того, что с помощью ИИ можно оптимизировать компиляторы того же C# в С++ вполне реально.
Native AOT развиваются, многие библиотеки подтягивают совместимость.
Возможно стоило бы расширить C# для создания объектов на стеке. Структуры к сожалению многого не поддерживают.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Pzz, Вы писали:
Pzz>Пипец какой. Ну т.е. содержательно, собралось как-то — ну и ладушки. Pzz>Как один инженер может за один месац понять хоть что-то в миллионе строк кода?
Pzz>Слабоумие и отвага...
Видимо им этот C++ как гвоздь в заднице — спецов мало, стоят дорого, обучать долго и дорого. И без него никак
Здравствуйте, Shmj, Вы писали:
Pzz>>Слабоумие и отвага...
S>Видимо им этот C++ как гвоздь в заднице — спецов мало, стоят дорого, обучать долго и дорого. И без него никак
Ну, я бы мелочи переписал, откровенно проблемные места переписал, а что работает, оставил бы и поддерживал. Для нового кода старался бы C++ не брать.
В конце концов, их любимый Rust вполне сочетается, насколько я в курсе, внутри одной программы с C++.
А так вот махом взять и переписать всё, со скоростью миллион строк кода на один человеко-месяц — это верный способ получить тонны кода, в котором старые проблемы в среднем сохранятся, появятся доселе невиданные новые, и в котором НИКТО НИЧЕГО НЕ ПОНИМАЕТ. IMHO, это ужас-ужас и кошмар.
Здравствуйте, Pzz, Вы писали:
Pzz>А так вот махом взять и переписать всё, со скоростью миллион строк кода на один человеко-месяц — это верный способ получить тонны кода, в котором старые проблемы в среднем сохранятся, появятся доселе невиданные новые, и в котором НИКТО НИЧЕГО НЕ ПОНИМАЕТ. IMHO, это ужас-ужас и кошмар.
Боюсь что так и будет. Причина — язык это целая философия, а не просто инструкции.
Здравствуйте, Shmj, Вы писали:
Pzz>>В конце концов, их любимый Rust вполне сочетается, насколько я в курсе, внутри одной программы с C++.
S>Это как? Нету сочетания — только стандартный FFI, с таким же успехом можете с Delphi сочетать...
Ну вот да, через FFI. Но насколько я понимаю, Rust сочетсяется с C через FFI в любую сторону. Т.е., можно в программу на Rust вставить запчасть на C, можно наоборот. Иди, попробуй в программу на C кусок на Haskell вставь. Или на Питоне даже, но так, чтобы работало нормально. У Питона тоже есть FFI.
Здравствуйте, Shmj, Вы писали:
Pzz>>А так вот махом взять и переписать всё, со скоростью миллион строк кода на один человеко-месяц — это верный способ получить тонны кода, в котором старые проблемы в среднем сохранятся, появятся доселе невиданные новые, и в котором НИКТО НИЧЕГО НЕ ПОНИМАЕТ. IMHO, это ужас-ужас и кошмар.
S>Боюсь что так и будет. Причина — язык это целая философия, а не просто инструкции.
И заметь, специфически-плюсовые проблемы, типа неаккуратного обращения с памятью, так может и поймают. Но собственно, если сравнимое количество ресурсов и усилий потратить на статический анализ C++ (давайте назовём это переписыванием с C++ на C++ ), то полагаю, сравнимое количество ошибок и будет найдено и устранено.
А вот логические ошибки, они никуда не денутся. Кроме того, совсем не факт, что ИИ перепишет алгоритмы, сохранив эквиавалентность исходного и переписанного алгоритма, т.е. тут тоже может понадобавлять ошибок. Которые вылезут в corner cases, совсем не факт, что покрытых тестами.
В общем, если они получили на это развлечение грант от Пентагона или АНБ, ну, молодцы, хороший бизнес. А если за свои, ну, такое себе.
Здравствуйте, Pzz, Вы писали:
Pzz>Ну вот да, через FFI. Но насколько я понимаю, Rust сочетсяется с C через FFI в любую сторону. Т.е., можно в программу на Rust вставить запчасть на C, можно наоборот. Иди, попробуй в программу на C кусок на Haskell вставь. Или на Питоне даже, но так, чтобы работало нормально. У Питона тоже есть FFI.
Здравствуйте, Shmj, Вы писали:
Pzz>>Ну вот да, через FFI. Но насколько я понимаю, Rust сочетсяется с C через FFI в любую сторону. Т.е., можно в программу на Rust вставить запчасть на C, можно наоборот. Иди, попробуй в программу на C кусок на Haskell вставь. Или на Питоне даже, но так, чтобы работало нормально. У Питона тоже есть FFI.
S>Можно: https://wiki.haskell.org/Foreign_Function_Interface
S>FFI — это одно из немногого, о чем человечество смогло договориться.
То, что из Хаскеля можно вызвать Си, нет никаких сомнений. Иначе он ни слова напечатать бы не мог.
А вот в другую сторону — там возникают всякие интересные проблемы с рантайном. И это совсем не то же самое, что FFI.
Например, на Go можно написать C-callable библиотеку (и динамическую и статическую). Но две такие штуки в одном процессе ужиться не могут (я, правда, давно на это нарывался, может с тех пор что-то и починили). Проблема в том, что два гошных рантайма в одном процессе не могут поделить tread-local storage, они как-то очень хитро на него садятся, и мешают друг другу.
Здравствуйте, Shmj, Вы писали:
S>Если бы в Rust добавили полноценное ООП — тогда бы было интересно.
не понимаю какого ООП вам там не хватает? Трейты — фактически абстрактные классы. Указатели есть. Пример на С++ который трудно/невозможно написать на Rust в студию.
Здравствуйте, sergii.p, Вы писали: SP>не понимаю какого ООП вам там не хватает? Трейты — фактически абстрактные классы. Указатели есть. Пример на С++ который трудно/невозможно написать на Rust в студию.
Ну вот пример:
С++
Скрытый текст
#include <iostream>
#include <memory>
class Base1 {
public:
virtual ~Base1() = default;
virtual void fun1() const {
std::cout << "fun1=" << a << std::endl;
}
virtual void fun2() const {
std::cout << "fun2=" << a << std::endl;
}
virtual void fun3() const {
std::cout << "fun3=" << a << std::endl;
}
virtual void fun4() const {
std::cout << "fun4=" << a << std::endl;
}
private:
int a = 0;
};
class V1 : public Base1 {
public:
void fun1() const override {
std::cout << "_fun1=" << a << std::endl;
}
private:
int a = 1;
};
class V2 : public V1 {
public:
void fun2() const override {
std::cout << "__fun2=" << a << std::endl;
}
private:
int a = 2;
};
class V3 final : public V2 {
public:
void fun3() const override {
std::cout << "___fun2=" << a << std::endl;
}
private:
int a = 3;
};
int main() {
const auto v3 = std::make_unique<V3>();
v3->fun1();
v3->fun2();
v3->fun3();
v3->fun4();
return 0;
}
Т.е. в наследнике вы трогаете только то что отличается. Все просто 3 класса, поочередно наследуются. Это может быть как UI-виджеты так и некая система событий.
А вот Rust аналог авто-генеренный
Куча сущностей вместо трех простых записанных, намноОООго сложнее для восприятия. Т.е. теряется простота. А в последнем V3 вам еще нужно помнить что было переписано в V2 — это на малом количестве методов — а если их будут сотни?
В общем — слишком сложный для восприятия ООП-код получается. Не пригодно для промышленного использования.
Здравствуйте, Shmj, Вы писали:
S>Видимо им этот C++ как гвоздь в заднице — спецов мало, стоят дорого, обучать долго и дорого. И без него никак
У Ханта специфический опыт. Сингулярити, тулы для С для решения проблем памяти. Это накладывает отпечаток на человека, а в реальности проблемы в индусах, процессах и отсутствии тестирования нормального.
Здравствуйте, Shmj, Вы писали:
S>В общем — слишком сложный для восприятия ООП-код получается. Не пригодно для промышленного использования.
Конкретно этот кусок кода можно было бы сделать или через ADT, или просто через одну структуру с навешенными туда лямбдами
Однако важнее другое. ООП — это, прежде всего, объекты с изменяемым состоянием (у тебя в примере это не выражено). Например, это полезно для десктопного GUI. Только Rust нацелен на многопоточные серверы (как особенно стало ясно после добавления async/await). А вот с многопоточкой ООП, знаешь, не очень-то и дружит из-за мутабельности... Да и эти жесткие правила по ссылкам, в тысячу раз более удобная семантика перемещения по сравнению с твоим C++ — все это хорошо заточено именно под многопоточку, под асинхронность (народ реально путается в семантике перемещения, когда пишет на C++, а потому предпочитает обходить ее стороной, а вот на Rust эта семантика также естественна как воздух). В общем, приоритеты такие, где ООП создало бы больше проблем, чем принесло пользы (из-за мутабельности, которой у тебя в примере нет)
А так. Я сам люблю баловаться десктопным программированием с GUI. Мне вот для таких задач ООП видится крайне полезным (особенно с линеаризацией наследования как в Common Lisp или Scala). Я совсем не против ООП, но вот в тех задачах, под которые заточен конкретно Rust — там ООП, скорее, мешает
И тут на самом деле, Rust далеко не единственный язык, где отказались от ООП из-за многопоточности и конкурентности. Пример другого языка — clojure
В одном учебнике по математическому программированию было написано, что не существует универсальных методов оптимизации, которые были бы хороши для всего. Готов перефразировать это и сказать, что точно также не существует универсальных языков программирования, которые были бы хороши для всего сразу. Я вот сейчас для себя освежаю знания по языку Scheme. До чего же красивый и выразительный язык! Но только Scheme (так же как С++, Rust, Java, C#) не является универсальным языком программирования (про термин "общецелевой язык программирования" все уже давно забыли — в 2026 году этот старый термин выглядит как выцветший кусок ткани). На Scheme было бы интересно написать какую-нибудь сложную логику и встроить в программу на С++ или на Java, но использовать для высоконагруженного сервера я бы не стал, ограничившись Java или даже С++ c Rust
То есть, твое желание видеть везде ООП похвально, но не всегда целесообразно, потому что ООП тоже не универсально!
Что касается исходной темы. Мне сдается, что с такими популяризаторами технологии и никаких конкурентов не надо!
Здравствуйте, dsorokin, Вы писали:
D>Только Rust нацелен на многопоточные серверы (как особенно стало ясно после добавления async/await). А вот с многопоточкой ООП, знаешь, не очень-то и дружит из-за мутабельности...
То есть браузеры, графические движки — лучше на нем не писать? Там лучше C++?
Могли бы добавить полноценное ООП, тогда пользователи могли бы сами делать выбор в каком случае что использовать.
А то что сейчас — это параша, смотрите мой пример. Вроде какой-то макрос был, чтобы не писать по сто раз всех наследников — но это полумеры. К полумерам не привык.
D>А так. Я сам люблю баловаться десктопным программированием с GUI. Мне вот для таких задач ООП видится крайне полезным (особенно с линеаризацией наследования как в Common Lisp или Scala). Я совсем не против ООП, но вот в тех задачах, под которые заточен конкретно Rust — там ООП, скорее, мешает
Но так его же хотят тащить и в браузеры и во все другое.
D>То есть, твое желание видеть везде ООП похвально, но не всегда целесообразно, потому что ООП тоже не универсально!
Так если в языке есть возможность ООП — вас никто не обязывает эту возможность использовать
Здравствуйте, Pzz, Вы писали:
Pzz>Слабоумие и отвага...
Там никто не знает, что этот код делает. Когда коду 30 лет. Чувак предложил попытаться победить копролит с помощью модного ныне LLM — это чисто политическое решение. Ибо если счас не изображаешь ярого фаната "Эй Ай", сильно рискуешь быть помеченным как "луддит" и сокращённым, чтоб освободить место "Эй Ай" специалистам.
Тем временем, часть open source проектов явно запретили коммиты с говно эй ай с мотивацией "мейнтейнерам нет желания читать тонны говнокода".
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, dsorokin, Вы писали:
D>>Только Rust нацелен на многопоточные серверы (как особенно стало ясно после добавления async/await). А вот с многопоточкой ООП, знаешь, не очень-то и дружит из-за мутабельности...
S>То есть браузеры, графические движки — лучше на нем не писать? Там лучше C++?
S>Могли бы добавить полноценное ООП, тогда пользователи могли бы сами делать выбор в каком случае что использовать.
S>А то что сейчас — это параша, смотрите мой пример. Вроде какой-то макрос был, чтобы не писать по сто раз всех наследников — но это полумеры. К полумерам не привык.
Так. Погоди! Давай разберем. Развесистую иерархию с глубоким наследованием я видел только в тулкитах GUI. Может быть, что это встречается где-то еще, но лично я не встречал больше нигде, хотя легаси-кода видел много разного, с которым приходилось работать. Причем, развесистая иерархия контролов GUI — это тоже вопрос еще, а насколько это все хорошо, потому что малейшее изменение в предках может привести к непредсказуемым изменениям в наследниках, ибо наследование реализации порождает сильную связность. А сильная связность — вещь не очень хорошая в плане перспективы поддержки
Раньше вот везде трубили, что наследуйте реализацию и будет вам счастье! Сейчас многие стали осторожнее высказываться. Мол, наследуйте интерфейс, а не реализацию, и тогда все будет хорошо, волосы будут шелковистыми и все такое (если ты застал еще на телеке рекламу про шелковистые волосы, то поймешь). Хотя грамотно спроектированный код можно и наследовать через реализацию, но ты сначала попробуй напиши такой код!
Так вот, подходим к главному моменту. Наследование интерфейсов есть в Rust! Как есть в Haskell, откуда они ее и взяли по сути — наследование характеристик, трейтов, они же классы типов. Трейт — это по сути и есть что-то вроде интерфейса, который могут поддерживать сразу одновременно разные типы данных.
То есть, понимаешь, если убрать из рассмотрения наследование реализации, то по сути все остальное из ООП есть и в Rust, и в Haskell. Там есть и инкапсуляция (через модули), есть и наследование интерфейсов, а полиморфизм виртуальных функций часто можно заменить лямбдами (не всегда, но часто). А наследование реализации, как мы выяснили выше, это несколько сомнительная вещь. Кажется, что вот мы выиграем с нею, выиграем в краткосрочном плане, а в долгосрочном плане наследование реализации может только усложнить поддержку кода, усложнить тестирование
Оставим теоретизирование. Теперь просто скажем, что ты несколько преувеличиваешь в своих выводах. Браузеры и графические движки можно писать и на Haskell, но лучше на языке без сборки мусора. Поэтому Rust тоже подходит, как и C++. И я не против C++ как такового. Я денежку зарабатываю на C++, но я против его сложности. Меня все возрастающая сложность C++ пугает и настораживает. И эта сложность выглядит как каток, который все сметает на своем пути, и который не остановить
Надеюсь, что я некоторые ключевые моменты довольно подробно описал
Здравствуйте, dsorokin, Вы писали:
D>А наследование реализации, как мы выяснили выше, это несколько сомнительная вещь. Кажется, что вот мы выиграем с нею, выиграем в краткосрочном плане, а в долгосрочном плане наследование реализации может только усложнить поддержку кода, усложнить тестирование
Но вот в браузерных движках оно активно используется в действующем коде. Вот пример:
Как видите — в самом современном браузере — лучше не бывает — используется многоуровневое (5 уровней) наследование. И что с этим делать? Представьте каким мусором это будет на Rust.
Или же нужно делать Rust++, как уже ранее MS делали J++ (емнип).
Здравствуйте, Артём, Вы писали:
Pzz>>Слабоумие и отвага...
Аё>Там никто не знает, что этот код делает. Когда коду 30 лет. Чувак предложил попытаться победить копролит с помощью модного ныне LLM — это чисто политическое решение. Ибо если счас не изображаешь ярого фаната "Эй Ай", сильно рискуешь быть помеченным как "луддит" и сокращённым, чтоб освободить место "Эй Ай" специалистам.
Ну так взял бы что-нибудь безопасное. Типа, рефакторинг говнокода с помощью ИИ. А не "взять — переписать". Ясно же, что не перепишет. А при этом взялся.
Аё>Тем временем, часть open source проектов явно запретили коммиты с говно эй ай с мотивацией "мейнтейнерам нет желания читать тонны говнокода".
Как их отличить-то, коммиты с ИИ от коммитов, написанных руками?
D>Так. Погоди! Давай разберем. Развесистую иерархию с глубоким наследованием я видел только в тулкитах GUI. Может быть, что это встречается где-то еще
15 лет назад (а более свежие проекты не хотелось бы светить) я реализовывал под винду application paravirtualization, в нем к примеру был класс узел реестра, класс узел файловой системы у которого еще был поднаследник файл, а оба они были наследованы от базового класса узел, который реализовывал базовые вещи для работы с путями, виртуальными хэндлами с подсчетом ссылок и прочее, наследники расширяли и отчасти модифицировали это все дело своим функционалом.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, Serginio1, Вы писали:
S> Вера это не наш удел. Но вероятность того, что с помощью ИИ можно оптимизировать компиляторы того же C# в С++ вполне реально. S>Native AOT развиваются, многие библиотеки подтягивают совместимость. S>Возможно стоило бы расширить C# для создания объектов на стеке. Структуры к сожалению многого не поддерживают.
Вроде unsafe появился, можно писать в цпп стиле на шарпе.
Для начала надо понять, о какой части системы идет речь. Kernel-mode, где ядро/драйвера? User-mode уровень самой ОС (ntdll/kernel32)? Прикладное ПО типа гуя/офиса/что-там-у-них-еще?
S>>Native AOT развиваются, многие библиотеки подтягивают совместимость. S>>Возможно стоило бы расширить C# для создания объектов на стеке. Структуры к сожалению многого не поддерживают. S>Вроде unsafe появился, можно писать в цпп стиле на шарпе.
пусть еще добавят цпп синтаксис, вместо этого нитакуси, и можно будет использовать)
Как много веселых ребят, и все делают велосипед...
Здравствуйте, Sharov, Вы писали:
S>> Вера это не наш удел. Но вероятность того, что с помощью ИИ можно оптимизировать компиляторы того же C# в С++ вполне реально. S>>Native AOT развиваются, многие библиотеки подтягивают совместимость. S>>Возможно стоило бы расширить C# для создания объектов на стеке. Структуры к сожалению многого не поддерживают.
S>Вроде unsafe появился, можно писать в цпп стиле на шарпе.
Ну я давно unsafe не пользовался. Все зависит от компилятора, unsafe использовали в большинстве для ускорения кода.
Сейчас Native AOT компилирует C# через IL в C++.
Что касается топика, то можно C++ компилировать в промежуточный язык типа IL, а из него в Rust.
C# очень хорошо декомпилируется.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Pzz, Вы писали:
Pzz>Ну так взял бы что-нибудь безопасное. Типа, рефакторинг говнокода с помощью ИИ. А не "взять — переписать". Ясно же, что не перепишет. А при этом взялся.
Насчёт что прямо кодовая база у MS это говнокод — очень сомневаюсь. Скорее наоборот, AI там накодит перлов.
Счас помимо моды на AI также мода на вытеснение C/C++ из системного кода, замену на Rust. Пока ещё Бидон был при власти — какой-то даже закон протолкнули, что нужно уже, пора.
Аё>>Тем временем, часть open source проектов явно запретили коммиты с говно эй ай с мотивацией "мейнтейнерам нет желания читать тонны говнокода".
Pzz>Как их отличить-то, коммиты с ИИ от коммитов, написанных руками?
Ментальный высер, не имеющий смысла, обильно покрытый комментариями. Я с этим столкнулся, да. Но я же не умею готовить. И кстати, в противовес AI генераторам также и продают AI-детекторы чтоб ловить студентов, так что даже и инструменты есть.
Вроде бы, если ввести документацию в markup там же в репке, развивать её с помощью AI же, вести ревизии и т.п., тогда результат AI намного меньше галлюцинирует в % соотношении от полезного кода — https://rsdn.org/forum/job/9017433.flat
Здравствуйте, Shmj, Вы писали:
S>В общем — слишком сложный для восприятия ООП-код получается. Не пригодно для промышленного использования.
ну мне выглядит ок. Чего сложного? Интерфейс явно выделен. Реализация максимально отделена. Дело привычки. Всё реализуемо.
В Rust хватает вещей которые совсем не реализованы и вот тогда действительно приходится извращаться. А как раз ООП реализовано довольно полно. Это же не Haskell. Вам даже мутировать не запрещают. Попрограммируйте на Haskell, потом вернитесь на Rust — рыдать будете от счастья.
Здравствуйте, sergii.p, Вы писали:
S>>В общем — слишком сложный для восприятия ООП-код получается. Не пригодно для промышленного использования.
SP>ну мне выглядит ок. Чего сложного? Интерфейс явно выделен. Реализация максимально отделена. Дело привычки. Всё реализуемо. SP>В Rust хватает вещей которые совсем не реализованы и вот тогда действительно приходится извращаться. А как раз ООП реализовано довольно полно. Это же не Haskell. Вам даже мутировать не запрещают. Попрограммируйте на Haskell, потом вернитесь на Rust — рыдать будете от счастья.
Мне тут давеча пришлось делать что-то вроде:
class abstract_reader {
public:
virtual ~reader();
int get_a() const = 0;
int get_b() const = 0;
... // и еще ряд чистых абстрактных методов.
};
class abstract_mutator : public abstract_reader {
public:
void set_a(int v) = 0;
void set_b(int v) = 0;
... // и еще ряд чистых абстрактных методов.
};
class basic_impl {
protected:
int calculate_a() const = 0;
int calculate_b() const = 0;
... // и еще ряд абстрактных методов.int impl_get_a() const {
... // какая-то логика, в которой вызывается calculate_a.
}
int impl_get_b() const {
... // какая-то логика, в которой вызывается calculate_b.
}
... // Еще сколько-то реализаций.void helper_1() { ... }
void helper_2() { ... }
... // Еще сколько-то вспомогательных методов.private:
... // какие-то данные класса.
};
class reader
: public abstract_reader
, protected basic_impl
{
public:
int get_a() const override { return impl_get_a(); }
int get_b() const override { return impl_get_b(); }
... // остальные методы из abstract_reader.protected:
// В реализациях этих методов используются helper_* из basic_impl.int calculate_a() const override { ... }
int calculate_b() const override { ... }
... // остальные методы из basic_impl.private:
... // какие-то данные класса.
};
class mutator
: public abstract_mutator
, protected basic_impl
{
public:
int get_a() const override { return impl_get_a(); }
int get_b() const override { return impl_get_b(); }
... // остальные методы из abstract_reader.void set_a(int v) override { ... }
void set_b(int v) override { ... }
... // остальные методы из abstract_mutator.protected:
// В реализациях этих методов используются helper_* из basic_impl.int calculate_a() const override { ... }
int calculate_b() const override { ... }
... // остальные методы из basic_impl.private:
... // какие-то данные класса.
};
Т.е. основной фокус в том, что большая часть общей логики reader/mutator была собрана внутри basic_impl. Причем в basic_impl нужны были специальные "точки кастомизации", которые были представлены виртуальными методами, а реализовывались эти методы в наследниках. Эта общая логика подмещивалась в reader/mutator через наследование от basic_impl.
Понятное дело, что все это чисто ООП-шное говно и воняет соответствующим образом. Но реальная жизнь есть реальная жизнь, на ООП-шном наследовании с виртуальными методами нужное мне получилось сделать достаточно быстро и без дублирования кода.
Интересно что бы пришлось делать в Rust-е? Реально интересно, без сарказма.
// rustc main.rs && ./main
//
// Вывод (по смыслу как в C++ версии):
// r first: reader{a=26, b=45} (get_a=26, get_b=45)
// r second (cached): reader{a=26, b=45} (get_a=26, get_b=45)
// m initial: mutator{a=30, b=30} (get_a=30, get_b=30)
// m after set_a(11): mutator{a=32, b=30} (get_a=32, get_b=30)
// m after set_b(100): mutator{a=32, b=127} (get_a=32, get_b=127)
// m set_ready(false)
// m.get_a(): Exception: object is not readyuse std::cell::Cell;
use std::fmt;
// --------- Error type (instead of C++ exception) ---------
#[derive(Debug, Clone, Copy)]
enum ReadError {
NotReady,
}
impl fmt::Display for ReadError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ReadError::NotReady => write!(f, "object is not ready"),
}
}
}
// --------- Interfaces (abstract_reader / abstract_mutator) ---------trait Reader {
fn get_a(&self) -> Result<i32, ReadError>;
fn get_b(&self) -> Result<i32, ReadError>;
fn describe(&self) -> Result<String, ReadError>;
}
trait Mutator: Reader {
fn set_a(&mut self, v: i32);
fn set_b(&mut self, v: i32);
}
// --------- "basic_impl" state (private base data) ---------struct BasicState {
ready: Cell<bool>,
cache_a_valid: Cell<bool>,
cache_b_valid: Cell<bool>,
cache_a: Cell<i32>,
cache_b: Cell<i32>,
}
impl BasicState {
fn new() -> Self {
Self {
ready: Cell::new(true),
cache_a_valid: Cell::new(false),
cache_b_valid: Cell::new(false),
cache_a: Cell::new(0),
cache_b: Cell::new(0),
}
}
fn validate_ready(&self) -> Result<(), ReadError> {
if self.ready.get() {
Ok(())
} else {
Err(ReadError::NotReady)
}
}
fn set_ready(&self, v: bool) {
self.ready.set(v);
}
fn invalidate_cache(&self) {
self.cache_a_valid.set(false);
self.cache_b_valid.set(false);
}
}
// --------- "basic_impl" logic + customization points (hooks) ---------trait BasicImpl {
// доступ к "private данным базового класса"fn basic(&self) -> &BasicState;
// hooksfn calculate_a(&self) -> i32;
fn calculate_b(&self) -> i32;
fn helper_mix(tag: &str, v: i32) -> i32 {
let salt = match tag {
"A" => 10,
"B" => 20,
_ => 0,
};
v + salt
}
fn impl_get_a(&self) -> Result<i32, ReadError> {
self.basic().validate_ready()?;
if !self.basic().cache_a_valid.get() {
let v = Self::helper_mix("A", self.calculate_a());
self.basic().cache_a.set(v);
self.basic().cache_a_valid.set(true);
}
Ok(self.basic().cache_a.get())
}
fn impl_get_b(&self) -> Result<i32, ReadError> {
self.basic().validate_ready()?;
if !self.basic().cache_b_valid.get() {
let v = Self::helper_mix("B", self.calculate_b());
self.basic().cache_b.set(v);
self.basic().cache_b_valid.set(true);
}
Ok(self.basic().cache_b.get())
}
fn impl_describe(&self) -> Result<String, ReadError> {
Ok(format!("a={}, b={}", self.impl_get_a()?, self.impl_get_b()?))
}
// "protected helpers"fn helper_invalidate_cache(&self) {
self.basic().invalidate_cache();
}
fn helper_set_ready(&self, v: bool) {
self.basic().set_ready(v);
}
}
// --------- reader ---------struct ReaderImpl {
basic: BasicState,
base: i32,
}
impl ReaderImpl {
fn new(base: i32) -> Self {
Self {
basic: BasicState::new(),
base,
}
}
}
impl BasicImpl for ReaderImpl {
fn basic(&self) -> &BasicState {
&self.basic
}
fn calculate_a(&self) -> i32 {
self.base * 3 + 1
}
fn calculate_b(&self) -> i32 {
self.base * self.base
}
}
impl Reader for ReaderImpl {
fn get_a(&self) -> Result<i32, ReadError> {
self.impl_get_a()
}
fn get_b(&self) -> Result<i32, ReadError> {
self.impl_get_b()
}
fn describe(&self) -> Result<String, ReadError> {
Ok(format!("reader{{{}}}", self.impl_describe()?))
}
}
// --------- mutator ---------struct MutatorImpl {
basic: BasicState,
a: i32,
b: i32,
}
impl MutatorImpl {
fn new(a: i32, b: i32) -> Self {
Self {
basic: BasicState::new(),
a,
b,
}
}
fn set_ready(&self, v: bool) {
self.helper_set_ready(v);
}
}
impl BasicImpl for MutatorImpl {
fn basic(&self) -> &BasicState {
&self.basic
}
fn calculate_a(&self) -> i32 {
self.a * 2
}
fn calculate_b(&self) -> i32 {
self.b + 7
}
}
impl Reader for MutatorImpl {
fn get_a(&self) -> Result<i32, ReadError> {
self.impl_get_a()
}
fn get_b(&self) -> Result<i32, ReadError> {
self.impl_get_b()
}
fn describe(&self) -> Result<String, ReadError> {
Ok(format!("mutator{{{}}}", self.impl_describe()?))
}
}
impl Mutator for MutatorImpl {
fn set_a(&mut self, v: i32) {
self.a = v;
self.helper_invalidate_cache();
}
fn set_b(&mut self, v: i32) {
self.b = v;
self.helper_invalidate_cache();
}
}
// --------- Demo ---------fn print_reader(title: &str, r: &dyn Reader) {
// как и в C++: здесь ожидаем, что объект "готов"let desc = r.describe().unwrap();
let a = r.get_a().unwrap();
let b = r.get_b().unwrap();
println!("{title}: {desc} (get_a={a}, get_b={b})");
}
fn main() {
let r = ReaderImpl::new(5);
print_reader("r first", &r);
print_reader("r second (cached)", &r);
let mut m = MutatorImpl::new(10, 3);
print_reader("m initial", &m);
m.set_a(11);
print_reader("m after set_a(11)", &m);
m.set_b(100);
print_reader("m after set_b(100)", &m);
m.set_ready(false);
println!("m set_ready(false)");
// хотим ровно как в C++:
// std::cout << "m.get_a(): ";
// try { std::cout << m.get_a(); } catch(...) { std::cout << "Exception: ..."; }
print!("m.get_a(): ");
match m.get_a() {
Ok(v) => println!("{v}"),
Err(e) => println!("Exception: {e}"),
}
}
Получилось в 1.66 раз больше кода
Т.е. если тупо переписать на Rust — будет больше кода и он будет сложнее. Боюсь что люди не смогут его поддерживать — поддержка тоже на плечи ИИ будет возложена.
Здравствуйте, so5team, Вы писали:
S>Интересно что бы пришлось делать в Rust-е? Реально интересно, без сарказма.
так а в чём проблема? Тупо заводишь в ИИ, он тебе генерирует. Я ж про что и говорю: перевод любого ООП кода на Rust не требует выворотов. Простые правила преобразования — с таким ИИ справляется на раз.
Отсуствие данных в BasicImpl. Дублировать одно и то же в Reader/Mutator -- это не нужная работа, которую приходится делать из-за заморочек Rust-а.
SP> Меня например в С++ часто утомляет искать от кого наследуется конкретная функция. Тут всё видно.
Не так-то просто в impl-е для Reader определить откуда берутся impl_get_a и пр. Хотя, наверное, это дело привычки.
Аё>>Тем временем, часть open source проектов явно запретили коммиты с говно эй ай с мотивацией "мейнтейнерам нет желания читать тонны говнокода". Pzz>Как их отличить-то, коммиты с ИИ от коммитов, написанных руками?
Очень отличается громоздкостью кода. Практически всегда можно написать раз в 10 лаконичнее и понятнее. Но — не спорю что это займет у мясных заметно больше времени. Про доводы что код должен быть в первую очередь читабелен все както и забыли как будто.
Вобщем, индустрию накрывает большой макаронный монстр пипец.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, sergii.p, Вы писали:
SP>ну мне выглядит ок. Чего сложного? Интерфейс явно выделен. Реализация максимально отделена. Дело привычки. Всё реализуемо.
Там приходится лишнюю работу делать — для каждого метода явно уточнять от какого наследника он тянется. А представьте что таких методов сотни? Дурная работа.
Возможно для некоторых вещей он и пригоден, но вот для браузреных движков, графики — где примитивы один от другого наследуются — не удобно.
Здравствуйте, sergii.p, Вы писали:
SP>ну мне выглядит ок. Чего сложного? Интерфейс явно выделен. Реализация максимально отделена. Дело привычки. Всё реализуемо.
Ну честно скажи — проще на C++ или на Rust этот прием? Кроме того в C++ есть заголовки, которые как бы кратко описывают контакт — и это правило. А Rust придется смотреть всю простыню кода.
S>Верите?
1) всё начнёт дико тормозить, жрать память и глючить
2) окажется на уровне ядра неработоспособно без онлайна с серверами в недружественных странах (и банить будет тоже ИИ, см. недавний случай про заблокированного яблом проповедника ябла)
Данное сообщение является художественным произведением и освещает вымышленные события в вымышленном мире. Все совпадения с реальностью являются случайными. Не является инвестиционной рекомендацией.
Здравствуйте, ononim, Вы писали:
O>Очень отличается громоздкостью кода. Практически всегда можно написать раз в 10 лаконичнее и понятнее. Но — не спорю что это займет у мясных заметно больше времени. Про доводы что код должен быть в первую очередь читабелен все както и забыли как будто.
Лаконично не всегда получается, если хочется добиться того, чтобы абстракции не текли в corner cases.
Понятный код писать очень сложно — гораздо сложнее, чем непонятный. И потом еще мучаешься, когда к слишком понятному коду приходит патч от понятливого читателя, который выводит какой-нибудь приватный символ в public, решая проблему этого самого понятливого читателя, но в то же время ломая сложный инвариант, которого он не заметил, и который не ломался, пока символ был приватным — потому что изнутри-то с ним обращались, как положено.
O>Вобщем, индустрию накрывает большой макаронный монстр пипец.
Люди уже привыкли к тому, что принтер может не печатать а сайт может не открываться. Это воспринимается в порядке вещей.
Я всё жду, привыкнут ли люди к тому, что из-за кривого софта могут падать механически исправные самолёты и взрываться атомные электростанции. Или когда это станет достаточно массовым, подходы к написанию софта всё жа начнут меняться.
Здравствуйте, Артём, Вы писали:
Pzz>>Ну так взял бы что-нибудь безопасное. Типа, рефакторинг говнокода с помощью ИИ. А не "взять — переписать". Ясно же, что не перепишет. А при этом взялся. Аё>Насчёт что прямо кодовая база у MS это говнокод — очень сомневаюсь. Скорее наоборот, AI там накодит перлов.
А если не говнокод, зачем её переписывать?
Аё>Счас помимо моды на AI также мода на вытеснение C/C++ из системного кода, замену на Rust. Пока ещё Бидон был при власти — какой-то даже закон протолкнули, что нужно уже, пора.
Я думаю, что я читал эту бумагу. Но это был не закон, а что-то вроде ежегодного отчёта АНБ по актуальным вопросам информационной безопасности. По каким-то их внутренним бюрократическим правилам президент США подписывает эту бумагу. Полагаю, не приходя в сознание.
Pzz>>Как их отличить-то, коммиты с ИИ от коммитов, написанных руками? Аё>Ментальный высер, не имеющий смысла, обильно покрытый комментариями. Я с этим столкнулся, да. Но я же не умею готовить. И кстати, в противовес AI генераторам также и продают AI-детекторы чтоб ловить студентов, так что даже и инструменты есть.
Я свой рукописный код обильно покрываю комментариями и бью по рукам джунов, которые этого не делают.
Здравствуйте, Pzz, Вы писали:
Pzz>Лаконично не всегда получается, если хочется добиться того, чтобы абстракции не текли в corner cases.
Pzz>Понятный код писать очень сложно — гораздо сложнее, чем непонятный.
В приведенных примерах именно ЧИТАТЬ сложно код на Rust. C++ получается более лаконично.
Данное сообщение является художественным произведением и освещает вымышленные события в вымышленном мире. Все совпадения с реальностью являются случайными. Не является инвестиционной рекомендацией.
Здравствуйте, Pzz, Вы писали:
Pzz>А если не говнокод, зачем её переписывать?
Потому, что это процесс, это было всегда, всё время существования профессии программиста. Конкретно на C/C++ нападки за их небезопасность, что ошибки, которые приводят к катастрофам, находят в коде, написанном 40 лет назад и куча людей смотрело, и не видело, как вот эта невинная строчка может вызвать перезаписть стека и "удачный" jump на адрес, помеченный как безопасный к исполнению.
Pzz>Я думаю, что я читал эту бумагу. Но это был не закон, а что-то вроде ежегодного отчёта АНБ по актуальным вопросам информационной безопасности. По каким-то их внутренним бюрократическим правилам президент США подписывает эту бумагу. Полагаю, не приходя в сознание.
Да, Бидон подписал бумагу. Но Трамп эту бумагу не отменил.
Pzz>Я свой рукописный код обильно покрываю комментариями и бью по рукам джунов, которые этого не делают.
А я нет. Если у меня возникает желание написать комментарий- это red flag, что код воняет. А дальше по ситуации — оставить ужас-ужас с комментарием, как оно работает и почему так, а не иначе, либо переписать правильно. Иногда бывало, что идея, как лучше сделать- приходила позже, и возвращался, чистил, необходимость в комментарии отпадала.
Это не отменяет правила хорошего тона комментировать сигнатуры интерфейсов / протоколов.
Здравствуйте, Артём, Вы писали:
Pzz>>А если не говнокод, зачем её переписывать? Аё>Потому, что это процесс, это было всегда, всё время существования профессии программиста. Конкретно на C/C++ нападки за их небезопасность, что ошибки, которые приводят к катастрофам, находят в коде, написанном 40 лет назад и куча людей смотрело, и не видело, как вот эта невинная строчка может вызвать перезаписть стека и "удачный" jump на адрес, помеченный как безопасный к исполнению.
Давно бы уже перестали выпендриваться, и сделали бы в C++-ном коде run time проверки выхода за границы/обращения по невалидному адресу обязательными...
Pzz>>Я думаю, что я читал эту бумагу. Но это был не закон, а что-то вроде ежегодного отчёта АНБ по актуальным вопросам информационной безопасности. По каким-то их внутренним бюрократическим правилам президент США подписывает эту бумагу. Полагаю, не приходя в сознание. Аё>Да, Бидон подписал бумагу. Но Трамп эту бумагу не отменил.
Так эта бумага — она типа ежегодного отчёта. Как можно отменить ежегодный отчёт?
Pzz>>Я свой рукописный код обильно покрываю комментариями и бью по рукам джунов, которые этого не делают. Аё>А я нет. Если у меня возникает желание написать комментарий- это red flag, что код воняет. А дальше по ситуации — оставить ужас-ужас с комментарием, как оно работает и почему так, а не иначе, либо переписать правильно. Иногда бывало, что идея, как лучше сделать- приходила позже, и возвращался, чистил, необходимость в комментарии отпадала.
Комментарий должен отвечать на вопрос "что?". На вопрос "как?" отвечает сам код.
Редко-редко приходится в комментарии таки объяснять "как?", если код алгоритмически нетривиален, или "почему?", если нетривиальна та хрень во внешнем мире, с которой этот код взаимодействует.
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, dsorokin, Вы писали:
D>>Только Rust нацелен на многопоточные серверы (как особенно стало ясно после добавления async/await). А вот с многопоточкой ООП, знаешь, не очень-то и дружит из-за мутабельности...
S>То есть браузеры, графические движки — лучше на нем не писать? Там лучше C++?
Зачем ООП в графическом движке?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, Pzz, Вы писали:
Pzz>Я всё жду, привыкнут ли люди к тому, что из-за кривого софта могут падать механически исправные самолёты и взрываться атомные электростанции. Или когда это станет достаточно массовым, подходы к написанию софта всё жа начнут меняться.
А в самолётах и АЭС и так другие подходы к написанию программ
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
Pzz>>Я всё жду, привыкнут ли люди к тому, что из-за кривого софта могут падать механически исправные самолёты и взрываться атомные электростанции. Или когда это станет достаточно массовым, подходы к написанию софта всё жа начнут меняться.
TB>А в самолётах и АЭС и так другие подходы к написанию программ
Ну туда тоже постепенно просочится. Мимо внимания эффективных менеджеров не пройдёт тот факт, что стоимость разработки софта для сайтиков и для самолётов различается на порядки величины.
Здравствуйте, Pzz, Вы писали:
Pzz>Давно бы уже перестали выпендриваться, и сделали бы в C++-ном коде run time проверки выхода за границы/обращения по невалидному адресу обязательными...
Если вектор, то через at() так и делается, через [] — в отладочной версии вроде обычно тоже.
Если что-то ещё, например самостоятельно выделенная память — то как ты представляешь это должно работать?
Здравствуйте, T4r4sB, Вы писали:
Pzz>>Я всё жду, привыкнут ли люди к тому, что из-за кривого софта могут падать механически исправные самолёты и взрываться атомные электростанции. Или когда это станет достаточно массовым, подходы к написанию софта всё жа начнут меняться.
TB>А в самолётах и АЭС и так другие подходы к написанию программ
Хз насчет самолётов и АЭС, но автомобильном коде ппц полный, говорят
Здравствуйте, Marty, Вы писали:
M>Хз насчет самолётов и АЭС, но автомобильном коде ппц полный, говорят
Кто говорит? Я помню ту историю с Тоётой у которой заклинило педаль газа, и там какая-то метрика показала что код очень очень сложный типа. Но мы не знаем, насколько эта метрика вообще адекватна
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
M>>Хз насчет самолётов и АЭС, но автомобильном коде ппц полный, говорят
TB>Кто говорит? Я помню ту историю с Тоётой у которой заклинило педаль газа, и там какая-то метрика показала что код очень очень сложный типа. Но мы не знаем, насколько эта метрика вообще адекватна
Да вообще почти любой эмбед код, который я видел, обычно это лютый пипец, потому что очень часто его пишут нихрена не программисты, а те же электронщики, которые задизайнили и развели схемоту.
На одном из последних мест работы, там был упоровшийся чел, и он сделал фреймворк для STMок на плюсах. Если бы он ограничился только периферией, то было бы даже неплохо, хотя, конечно, код там довольно списифисский
Но там и строки и вектора, которые при недостатке памяти просто нахер данные молча отбрасывают, да и вообще там такие кучи граблей поразложены были. Но это было таки одно из самых качественных из виденного мной.
Хотя, сейчас вот проект на чистой сишечке, и тут уже вполне годно делается. Пожалуй, первый раз в эмбеде подобное вижу