All streams
Search
Write a publication
Pull to refresh
78
0
Send message
Но если отключаешь динамику, то начинается адище — либо как в статье, либо ETL (который имхо в обозримом будущем подавится и упадет под диван), в общем широкий набор способов создать новый язык. Это плохо само по себе, к тому же туго ложится на индустрию.

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


(Правда велосипеды вместо std::function и std::span таки изобрелись)


Кстати, почему тремя?

Ну, обычно что-то в духе -fno-exceptions -fno-rtti и еще какой-нибудь финт, чтобы динамику отключить. В опциях gcc я не так хорошо ориентируюсь, вполне может быть достаточно сделать --specs=nano.specsвместо трех отдельных опций.

Иногда приходится использовать библиотеки, которые кучу используют (хоть и позиционируются как embedded), например, ST этим регулярно грешат.
Или, скажем, lwip — да, pbuf'ы выделяются не в обычной куче, а в пуле, но это решает только проблему с фрагментацией, а память как текла, так и течет :)

Да, необходимость отказываться от динамических аллокаций довольно сильно мешает писать прошивки на С++; но на мой взгляд это все равно лучше, чем писать на С — да, стандартными контейнерами не попользуешься (но можно написать свои или взять https://www.etlcpp.com/), да, std::function не поюзаешь (но можно написать свою реализацию без динамических аллокаций).
К счастью, все эти вещи можно отключить буквально тремя опциями компилятора, и форсировать это на уровне соглашения о стиле кода.


Зато шаблоны, лямбды, RAII и ООП без ручных манипуляций с указателями.

Среди засилья плохих и быстрых переводов эта статья читается очень приятно!
Отдельное спасибо переводчику за старания!

Мы тогда хотели большой рубин для лазера сделать, но не смогли найти жалкие 0,5% оксида хрома от объема оксида алюминия, а то маленького рубина из старого будильника не хватало для этой цели, поэтому решили сделать хотя бы корунд.

Интересно, а нельзя ли было добыть оксид хрома из пасты ГОИ? Вроде достаточно доступная штука в советское время была.

Еще макросы, в отличие от лямбд и инлайн-функций, позволяют менять control-flow (т.е. делать return или break из внешней области).

Я пару раз делал подключал бинарные файлы через objcopy --input-target binary
Быстрый гуглинг так же предлагает https://github.com/graphitemaster/incbin.


А вообще — ждем принятия соответствующего Proposal и облизываемся на растовый std::include_bytes

Хммм, но при этом есть Github Action, который собирает версию под линуксы; правда я что-то не могу сходу понять, с какими ключами. По идее нужна опция -Wuninitialized, которая часть -Wall.

Интересно, чем (и с какими ключами) этот проект компилируется в норме? gcc вроде бы умеет о таком предупреждать.

Очень основательный ответ, приятно читать!

В свою очередь рад, что вы вообще идете на обсуждение :)


Да, но ведь ошибки нужно минимизировать в любом коде, не важно, сложный это алгоритмический код или чисто техническая штука. Любой код полезно писать максимально чисто.

Верно, но очень уж обидно тратить целый день на идиотскую ошибку в парсинге, когда вообще непонятно, в чем же ошибка заключается!
Я вот представляю, что я студент-новичок — и реально не знаю даже, с чего начинать-то? В какую сторону думать? Каждую строчку перебирать?


Нам кажется что сценарий
«Тест упал -> иду к наставнику -> наставник задаёт вопрос о логике моего алгоритма/советует вспомнить про краевые случаи -> я отвечаю на вопросы или следую советам наставника, сама додумываюсь до проблемы в коде»

лучше, чем сценарий

«Тест упал -> я взяла тесткейс, нашла в коде баг, поправила, отправила в систему опять»

Несложно заметить, что во втором сценарии я гораздо меньше думаю. Студенты, которые ошибаются и проводят плодотворную работу над ошибками вместе с наставниками, по-моему, лучше и быстрее “набьют руку”. Безусловно, это непростой путь, но он точно результативный.

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


В случае открытого теста думать, скорее всего, то же придется — если ошибка в алгоритме и если она не глупая опечатка, то придется придумывать, что с ней делать.
Можно так же возразить, что при этом у студента не будет ощущения, что ему помогали, нет, он всё сам!


За этим мы следим, стараемся помогать тем, кому сложно. Человек никогда не уходит от нас незаметно, так что все такие случаи известны и посчитаны

Это само по себе очень хорошо, но не лучше ли предотвратить страдания, а не "заглаживать вину" постфактум?


Мы считаем, что да, помогают, это консенсус многих преподавателей и программистов, с которыми мы обсуждали курс.
Наверное, чтобы доказать это или опровергнуть раз и навсегда, нужен эксперимент. Подумаем, как его устроить, чтобы не напугать студентов :)

Как видите, здесь в комментариях довольно много людей с противоположным мнением :) Возможно, что ваш консенсус — это следствие confirmation bias и каких-то других групповых когнитивных искажений типа пузыря фильтров? Или еще каких-то умных слов, которыми я пытаюсь сказать, что люди с одинаковым мнением стремяться общаться только друг с другом и соглашаться друг с другом, тем самым укрепляясь в своем мнении.


Опять же, не могу привести исследование сейчас, но думаю, устроим что-то подобное вместе со студентами, которые будут не против.

Отлично :) Надеюсь, что если устроите, то опубликуете результаты!


Мы думаем в сторону того, чтобы дать подсмотреть «по кнопке» несколько тестов. Большинство тестов всё равно довольно объемные и их открытие вряд ли сильно поможет.

Если тесты объемные, то странно, что вы боялись "подгона под ответ"…
Вообще же даже объемные можно предлагать скачать как файл, например, чтобы студент мог локально потестить, было бы желание.


Спасибо, что участвуете в обсуждении и предлагаете варианты, нам это важно.

Пожалуйста :)

И да, конечно мы рассказываем им почему тесты закрыты и подробно объясняем что нужно делать, если не получается побороть тест.

Это хорошо!


Тестирование на наш взгляд — важная часть обучения алгоритмам.
Если не умеешь реализовывать алгоритм так, чтобы код работал — значит не научился алгоритмам (в нашем понимании).
Чтобы писать рабочий код, надо уметь его тестировать, видеть разные кейсы.

Тем не менее я не вижу в этом прямой корреляции с закрытыми тестами.
С вашего позволения, я повторю свои аргументы все в одном месте.


  • Закрытые тесты не позволяют отделить ошибки в алгоритме от ошибок в разборе входных данных или от "неправильного" прочтения задания, которое почти неизбежно в определенном проценте случаев.
  • Закрытые тесты означают, что ваши наставники тратят больше времени на общение со обучающимися, разъясняя вещи, которые можно было бы просто увидеть в результатах тестов (т.е. буквально выполняют работу машин). Время ваших сотрудников, которое оплачивает ваша компания!
  • Закрытые тесты скорее всего приводят к большей фрустрации учащихся и к большему уровню недовольства курсом в целом. Понятно, что ваша цель — научить людей алгоритмам, но как знать, сколько из них бросают это дело, потому что "аргх ничего непонятно опять ошибка!"?
  • Закрытые тесты не похожи ни на реальное программирование, ни на реальное самостоятельное написание тестов. Неясно, действительно ли они помогают научиться тестировать код, по крайней мере курсы или книги по юнит-тестированию вроде бы такое не практикуют массово?
  • Непонятно, приводят ли закрытые тесты к лучшему или худшему уровню понимания алгоритмов или программирования в целом (мне исследований на такую тему не попадалось, но мб я плохо искал). Тем не менее, можно в рамках вашего же курса это проверить — учащихся много, вполне можно устроить небольшое исследование.
  • Вероятно, открывать тесты по желанию учащегося было бы разумным компромисом (типа, нажать на кнопочку и согласиться с предупреждением). По факту вы ведь сейчас так и делаете! Только с привлечением живого человека, которому, опять же, нужно оплачивать его время, который не может ответить всем сразу, который мог бы отвечать на более интересные вопросы. А учащийся должен ждать этого ответа какое-то (полагаю, не очень малое) время, что тоже усиливает фрустрацию.

Минутка субъективизма

Лично я проходил несколько курсов (в т.ч. 3 или 4 по алгоритмам так или иначе) — тесты везде были открыты. В одном даже вместе с заданием выдавалась пачка тестовых кейсов, которые можно было запускать локально.
На мой субъективный взгляд — это были лучшие курсы с лучшими преподавателями, которые я в жизни видел. Подогнать код под ответ было невозможно, потому что реальные тесты содержали гигантские входные данные, это было проще сделать правильно, чем подогнать!


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


Соответственно весь мой опыт восстает против закрытых тестов, но опираться только на свой опыт — неправильно. Вероятно опыт ваших сотрудников говорит об обратном.
Поэтому было бы здорово как-то объективно сравнить результаты.

Вы считаете, что алгоритмы можно понять только с помощью медитации над кодом, а не с помощью отладки?

Но у вас же все-таки курс по алгоритмам, а не по юнит-тестированию?


Я в первую очередь говорю, что в реальной жизни проблемы себя так не проявляют, есть хоть какой-то симптом, хоть какой-то способ понять, в чем дело. Закрытый тест-кейс — это буквально "пойди туда, не знаю куда, найди то, не знаю что".


В реальности я не буду сидеть и просто медитировать над кодом, пытаясь понять, что не так, по крайней мере не в первую очередь! Я буду вставлять отладочную печать, читать логи, запускать анализаторы, выполнять код по шагам, буду изолировать проблемное место.


Тем не менее, и мои и ваши аргументы явно основаны на личных предпочтениях. Было бы здорово, если бы мы могли их как-то более весомо подкрепить.
Не попадались ли вам какие-нибудь исследования на эту тему? Можно ли ввести какие-то объективные метрики? Хотя бы, не знаю, сравнить несколько групп с закрытыми и с открытыми тестами.


Еще, кстати, момент — а вы студентам-то в самом курсе объясняете, почему тесты закрыты?

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


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


Ну или писать в поддержку и тратить дорогостоящее время ваших специалистов.

По-моему все-таки "У вас в коде ошибка" — это не особенно похоже на реальность. В реальности мы знаем хоть что-то об ошибке — как она проявляется, в чем она заключается, при каких условиях, почему ее надо исправлять.
Не бывает же так, что начальник просто приходит и говорит "поправь код" и уходит.


И чего плохого в том, что люди будут просто подгонять код так, чтобы он проходил тесты? Если тест можно пройти с помощью подгона, то он плохо написан, недостаточно подробен или недостаточно въедлив.
Так же, как в TDD — мы пишем ровно столько кода, сколько необходимо для прохождения тестов :)

Поддержу, еще "Сквозь время" у него же.

Если кто-нибудь порекомендует фантастику, в которой будущее — не просто увеличенное в несколько раз настоящее, буду весьма признателен :)


От себя порекомендую "2048" Шелли.

https://godbolt.org/z/M9shEz — потому что это валидно только в С99, не в С++

Справедливо, но я скорее имел в виду что одномерные массивы не передают по "указателю на массив", а просто парой "обычный указатель + размер". Поэтому-то и возникает путаница из-за такого названия — что "указатель на массив" не используют… чтобы указывать на одномерный массив.


Насколько я знаю, в С99 уже можно задавать размеры в рантайме, в т.ч. для многомерных (формально это вроде как считается VLA и нужно соблюдать порядок аргументов):


void foo( size_t n, int (*a)[n])
{
    a[1][1] = 1;
}

int main(void) {

    void * array = malloc( 8*9*sizeof(int) );
    foo( 9, array );
}

Но полагаю, что все уже успели привыкнуть делать иначе.

Information

Rating
4,829-th
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Registered
Activity