Здравствуйте, serg_joker, Вы писали:
S>>А вот каково ваше отношение к [[nodiscard]]? _>Так очевидно же. nodiscard же только генерирует предупреждения в случае чего, а предупреждения "мы" игнорируем.
Чего-то подобного я и ожидаю, но хотелось бы все-таки послушать начальника транспортного цеха...
PS. Сам уже не понимаю как мы до C++17 без этого атрибута жили. Благо компиляторы позволяли его использовать даже в рамках C++11 и C++14.
Здравствуйте, serg_joker, Вы писали:
_>Какие "модные" практики ты видишь такие, что ухудшают качество программистов? Именно практики как таковые, а не их догматическое и чисто формальное использование. Вот так, чтоб практику отменить — и программисты стали лучше.
Ну, например, сейчас больше принято полагаться на тестовое покрытие как критерий корректности кода, чем на какое-либо умственное обоснование. Что приводит к утрате умения рассуждать о корректности кода головой (и заодно снижает степень понимания кода, как своего, так и чужого, и степень понимания используемого API).
Повсеместная практика code review двояка по последствиям. С одной стороны, это хорошо, если код посмотрит другая пара глаз (хотя зачастую ревьювер смотрит код весьма формально, у него и своей работы полно). С другой, это задерживает путь прохождения изменений в репозиторий. Автор коммита вынужден, в ожидании ревью, переключаться на другие задачи. Это рассеивает внимание.
Ну и т.д. Я описал общее ощущение, к серьёзной дискуссии на эту тему я не готов.
Pzz>>Опенсорс бывает разный. У libtiff огромная пользовательская база, и написан он вполне приличным и уважаемым человеком. А код там такой, что хочется его развидеть, пока глаза не отвалились. _>Ну вот я его заверну аккуратно, чтобы ворнингами не сыпало, и буду пользоваться. Большая пользовательская база такой низкоуровневой хрени — это уже некая гарантия качества (на уровне предоставляемого функционала). Что там внутри меня мало интересует до тех пор, пока мне не нужно будет колупаться в исходниках.
Его кормят снаружи данными в весьма сложном и нетривиальном формате. Тебе его придется в контейнер обернуть, чтобы быть уверенным, что он в тебя не выстрелит.
Здравствуйте, so5team, Вы писали:
Pzz>>Ну а как люди пишут крупные системы на JS или Питоне? Там с проверками еще сильно хуже.
S>С какими именно проверками? S>Так-то JS и Python -- это языки со строгой типизацией, в отличии от C или C++. S>В них по ошибке строку невозможно выдать за double.
JS-то, как раз, без проблем даст сложить строку с числом
Питон да, не даст.
Но оба языка дадут положить в массив или словарь значение неподходящего типа (например, по ошибке, не поле какого-то объекта, а ведь объект целиком). И выстрелит это в момент использования.
S>А именно крупные системы пишут с трудом и за счет тотального тестирования. Не зря же сама мода на unit-тестирование в индустрию пришла из extreme programming, который возник из опыта разработки большого проекта на динамически-типизированном SmallTalk.
Мой тезис: отсутствие проверок усложняет разработку, но не делает её невозможной.
Я к тому, что всяческие статические проверки — это хорошо. Но не надо по их поводу истерику устраивать.
Кстати, моё личное мнение: динамически типизованные языки плохо подходят для первоначального обучения программированию. Статическая типизация не только следит за руками, но еще и приучает систематически думать наперёд. Если начинать с динамически типизованного языка, в котором "всё можно", этот навык не развивается.
A>Допустим у нас есть несколько (ну допустим пять) величин: метры, килограммы, секунды, ньютоны и джоули. A>Да, их нельзя складывать с друг с другом. Но их можно(нужно) умножать и делить. A>Таким образом, чтобы написать формулу, которая содержит три величины, нам нужно иметь 3*(5+1)*(5+1) типов данных. A>То есть 36 типов для результатов умножения (килограмм*метр), A>И 2*36 типов для деления килограмм/метр и метр/килограмм. A>То есть, что-то около сотни типов. (Точная цифра =108)
Возможности:
1. Независимые типы данных, такие как mass и length. Присвоить один другому нельзя — будет ошибка компиляции.
2. Автоматическое конвертирование величин одной и той же размерности из одной системы единиц в другую. К примеру, присвоив килограммам один грамм, в результирующей переменной (si::mass) обнаружим 0.001. Вычисление коэффициентов преобразования производится в compile time.
3. Контроль за корректностью формул со стороны компилятора. Так, если ускорению попытаться присвоить результат деления длины на время, возникнет ошибка компиляции. С моей точки зрения, это наиболее важное свойство моего кода. Особенно это заметно на трехэтажных формулах, где очень легко потерять из виду, какая же в результате получается размерность. В случае использования моего кода подобного рода ошибки полностью исключаются.
Здравствуйте, so5team, Вы писали:
Pzz>>как критерий корректности кода, чем на какое-либо умственное обоснование
S>А это вообще как?
S>Некто alpha21264 или Pzz порассуждал, начирикал что-то на бумажке и заключил "код корректен"?
Давай так. Или ты не будешь хамить. Или я не буду с тобой разговаривать.
Мне интересен разговор с коллегами в формате обмена знаниями, мнениями и опытом, а не в формате кунания друг друга головой в чан с говном.
S>Или же это "умственное обоснование" должно быть как-то формально быть записано, да еще и так, чтобы проходить хоть какую-то верификацию.
Мне как-то помнится пришлось начальника припрячь оторваться от его начальничьих дел и выслушать моё формальное доказательство сложного куска кода. Но это хорошо, что под рукой был человек с математическим образованием, способный поддерживать разговор на таком уровне.
Здравствуйте, Pzz, Вы писали:
Pzz>Ну и т.д. Я описал общее ощущение, к серьёзной дискуссии на эту тему я не готов.
Да я тоже.
Ну вот мне кажется, что всё-таки многие практики, будучи приложены к абизянам, безопасность не ухудшают.
Не-абизяны на то и не-абизяны, чтобы думать, где чего применять, а где нет. Ну и стараться не работать там, где практики применяются бездумно и формально.
Pzz>Его кормят снаружи данными в весьма сложном и нетривиальном формате. Тебе его придется в контейнер обернуть, чтобы быть уверенным, что он в тебя не выстрелит.
Убедил, всеми силами буду стараться держаться от него подальше
Здравствуйте, Pzz, Вы писали:
S>>Так-то JS и Python -- это языки со строгой типизацией, в отличии от C или C++. S>>В них по ошибке строку невозможно выдать за double.
Pzz>JS-то, как раз, без проблем даст сложить строку с числом
Я вообще не о том говорил. В C и C++ вы можете скастовать void* к double* и начать работать с double, хотя по факту за void* был спрятан char*.
Pzz>Но оба языка дадут положить в массив или словарь значение неподходящего типа (например, по ошибке, не поле какого-то объекта, а ведь объект целиком). И выстрелит это в момент использования.
Поэтому нормальный проект на языке с динамической типизацией невозможен без плотного покрытия тестами.
И, что характерно, именно это и делают.
Pzz>Мой тезис: отсутствие проверок усложняет разработку, но не делает её невозможной.
Pzz>Я к тому, что всяческие статические проверки — это хорошо. Но не надо по их поводу истерику устраивать.
"Истерику", как вы выразились, устраивают не по поводу отсутствия статических проверок, а по поводу сознательного отказа некоторых индивидов от их применения.
Казалось бы, в твоем распоряжении инструмент, который позволяет забесплатно и автоматически снять с тебя нехилый кусок головной боли.
Но ты от этого отказываешься, да еще и кичишься этим.
Что уже странно, по меньшей мере.
Еще более странно, что не расказывают а чем же компенсируют отсутствие такого контроля.
Моя версия, которую, к сожалению, не представляется возможным проверить -- это работа alpha21264 над небольшой и стабильной кодовой базой в небольшой команде. Да еще и, вероятно, в условиях, когда сама прикладная задача достаточно старая и хорошо изученная. И в которой, могу предположить, математика и физика на пару порядков важнее чем код, в который превращаются итоговые формулы.
Здравствуйте, serg_joker, Вы писали:
Pzz>>Ну и т.д. Я описал общее ощущение, к серьёзной дискуссии на эту тему я не готов. _>Да я тоже. _>Ну вот мне кажется, что всё-таки многие практики, будучи приложены к абизянам, безопасность не ухудшают. _>Не-абизяны на то и не-абизяны, чтобы думать, где чего применять, а где нет. Ну и стараться не работать там, где практики применяются бездумно и формально.
Проблема в том, что человек — существо высокосоциальное. И если он будет работать в команде, состоящей в основном из обезьян, с соответствующими практиками, ну, в конце концов он и сам превратится в обезьяну.
Pzz>>Его кормят снаружи данными в весьма сложном и нетривиальном формате. Тебе его придется в контейнер обернуть, чтобы быть уверенным, что он в тебя не выстрелит. _>Убедил, всеми силами буду стараться держаться от него подальше
А куда ты денешься, PDF использует евонные кодеки.
Здравствуйте, so5team, Вы писали:
S>Из разговра с вами стало понятно, что ряд нововведений в С++ вы считаете бесполезными.
Большую часть того, что появилось после 2010 года.
Если уже даже сам Страуструп говорит, что он знает С++ только на 80%...
Керниган говорил Ричи, когда тот предлагал внести в язык очередную фичу, — если тебе нужен PL/1 ты знаешь, где его взять.
Сейчас современный С++ намного превосходит тот самый монстрообразный PL/1.
Это неправильно. Язык должен быть простым, чтобы программист думал не над языком, а над задачей.
S>А вот каково ваше отношение к [[nodiscard]]?
S>Можно предположить, что "нормальные программисты" (tm) никогда не игнорируют возвращаемые функциями/методами значения. И посему [[nodiscard]] -- всего лишь бесполезный "синтаксический оверхэд" (c)
Ну в общем да. Один раз в жизни это предупредит меня об ошибке, а всё остальное время это будет засирать код.
Слова "один раз в жизни" достаточно ярко выделены?
И что мне делать, если мне действительно не нужно возвращаемое значение? Заводить неиспользуемую переменную?
Или есть какое-то специальное слово "мне действительно не нужно возвращаемое значение"?
Писать вот так?
(void)ваша_дурацкая_функция();
А кроме того, это просто уродливо. Скажите, ну вот зачем тут [[nodiscard]] сразу двое квадратных скобок?!
Здравствуйте, Pzz, Вы писали:
S>>Некто alpha21264 или Pzz порассуждал, начирикал что-то на бумажке и заключил "код корректен"?
Pzz>Давай так. Или ты не будешь хамить.
Или вы перестанете выискивать черную кошку в черной комнате.
S>>Или же это "умственное обоснование" должно быть как-то формально быть записано, да еще и так, чтобы проходить хоть какую-то верификацию.
Pzz>Мне как-то помнится пришлось начальника припрячь оторваться от его начальничьих дел и выслушать моё формальное доказательство сложного куска кода. Но это хорошо, что под рукой был человек с математическим образованием, способный поддерживать разговор на таком уровне.
Давайте переведем вашу историю в более содержательное русло.
Вы с помощью некого формального аппарата вывели доказательство корректности кода.
Далее вы устным образом рассказали это доказательство и оно было принято.
Пока все верно?
Если да, то было ли это доказательство зафиксированно в неком виде, позволяющем провести формальную верификацию посредством программных инструментов?
Здравствуйте, so5team, Вы писали:
S>Давайте переведем вашу историю в более содержательное русло.
Давайте.
S>Если да, то было ли это доказательство зафиксированно в неком виде, позволяющем провести формальную верификацию посредством программных инструментов?
Здравствуйте, alpha21264, Вы писали:
A>Это неправильно. Язык должен быть простым, чтобы программист думал не над языком, а над задачей.
При этом есть мнение, что сложность инструмента должна быть сопоставима со сложностью решаемой задачи, иначе образуется слишком большой семантический разрыв.
A>Ну в общем да. Один раз в жизни это предупредит меня об ошибке, а всё остальное время это будет засирать код. A>Слова "один раз в жизни" достаточно ярко выделены?
Да.
A>И что мне делать, если мне действительно не нужно возвращаемое значение?
В стиле современного C++ это должно записываться так:
std::ignore = some_func();
Однако, было бы интересно узнать, а в каких-таких ситуациях можно игнорировать помеченное как [[nodiscard]] значение?
Я сходу могу назвать всего две:
1. Когда кто-то бездумно расставил [[nodiscard]]. По принципу "прикажи дураку богу молиться, он и лоб расшибет".
2. В unit-тестах, когда на возникающие ошибки реально пофиг.
В продакшен коде, наверное, вспоминаются разве что отдельные noexcept-контексты, вроде деструкторов или секций catch, в которых нужно сделать очистку ресурсов или откат ранее выполненных операций. И тогда, т.к. мы не можем бросать исключения, приходится игнорировать коды возврата у вызываемых функций/методов.
Но тогда std::ignore как раз указывает, что мы поступаем так намеренно.
Здравствуйте, Pzz, Вы писали:
S>>Если да, то было ли это доказательство зафиксированно в неком виде, позволяющем провести формальную верификацию посредством программных инструментов?
Pzz>Нет.
А теперь вопрос: через какое-то время после вас этот код был модифицирован Васей Пупкиным. Что поможет Васе понять, что он ничего не поломал?
Упарывание юнит-тестами имеет свои негативные стороны, но оно хотя бы решает проблему подобных проверок без привлечения механизмов автоматической формальной верификации.
Здравствуйте, so5team, Вы писали:
Pzz>>JS-то, как раз, без проблем даст сложить строку с числом
S>Я вообще не о том говорил. В C и C++ вы можете скастовать void* к double* и начать работать с double, хотя по факту за void* был спрятан char*.
Не, ну это всё же специально стараться надо. Случайно так не ляпнешь.
Кстати, union — более удобный инструмент, чтобы так насвистеть, чем кастирование через void*
S>Казалось бы, в твоем распоряжении инструмент, который позволяет забесплатно и автоматически снять с тебя нехилый кусок головной боли. S>Но ты от этого отказываешься, да еще и кичишься этим.
Сколько лет ушло у линуксячего ядра, чтобы наконец вычистить предупреждения? (да и то я не уверен, что их вычистили целиком).
S>Моя версия, которую, к сожалению, не представляется возможным проверить -- это работа alpha21264 над небольшой и стабильной кодовой базой в небольшой команде. Да еще и, вероятно, в условиях, когда сама прикладная задача достаточно старая и хорошо изученная. И в которой, могу предположить, математика и физика на пару порядков важнее чем код, в который превращаются итоговые формулы.
Можно чуть-чуть обобщить.
Есть класс задач, в которых именно прикладной уровень обладает высокой степенью сложности. Например, из-за сложной физики-математики, как в вашем примере. Или из-за алгоритмической сложности. Например, задача написания оптимизирующего компилятора. Заметим, в ней именно "математика" сложна.
В таких задачах люди типа даже не Альфы (про него, живого, мы мало чего знаем), а описанной вами чуть выше модели альфы вполне могут работать.
gcc внутри, кстати, примерно так и написан. Но назвать его говнокодом у меня как-то язык не поворачивается. Все-таки, большая часть мировой кодовой базы вполне успешно через него проходит и выдаёт на выходе вполне работоспособный машинный код.
Здравствуйте, so5team, Вы писали:
S>А теперь вопрос: через какое-то время после вас этот код был модифицирован Васей Пупкиным. Что поможет Васе понять, что он ничего не поломал?
Да, это болезненный вопрос. К тому же, я имею тенденцию сочетать алгоритмическую сложность с аккуратным оформлением кода. Это наводит Васю Пупкина на (ложную) мысль, что он в этом коде способен разобраться.
Даже рантайм-проверки не помогают. Вася их убирает, когда они срабатывают, скотина такая.
S>Упарывание юнит-тестами имеет свои негативные стороны, но оно хотя бы решает проблему подобных проверок без привлечения механизмов автоматической формальной верификации.
Говорят, когда в машинах массво появились ремни безопасности, люди не стали реже гибнуть на дорогах. Люди стали быстрее ездить.
Я не против тестов. Но к ним что-то еще должно прилагаться.
Здравствуйте, Pzz, Вы писали:
_>>Не-абизяны на то и не-абизяны, чтобы думать, где чего применять, а где нет. Ну и стараться не работать там, где практики применяются бездумно и формально.
Pzz>Проблема в том, что человек — существо высокосоциальное. И если он будет работать в команде, состоящей в основном из обезьян, с соответствующими практиками, ну, в конце концов он и сам превратится в обезьяну.
В целом согласен (с оговорками про высокосоциальность прям каждого индивидума), поэтому выделенная часть. Ну и вообще выбор коллектива — это очень важно. Если есть такая возможность, то с неумными людьми лучше не работать, жизнь слишком коротка для этого. И уж точно не работать, если неумные люди будут активно влиять на то, как придётся тебе. В том числе, и особенно, если неумные люди — начальство.
_>>Убедил, всеми силами буду стараться держаться от него подальше Pzz>А куда ты денешься, PDF использует евонные кодеки.
Я имел ввиду работу с библиотекой как программист.
Здравствуйте, Pzz, Вы писали:
S>>Я вообще не о том говорил. В C и C++ вы можете скастовать void* к double* и начать работать с double, хотя по факту за void* был спрятан char*.
Pzz>Не, ну это всё же специально стараться надо. Случайно так не ляпнешь.
Да сколько угодно как только народ начинает пропихивать информацию через void*.
Например, если есть callback-и с дополнительным параметром userData, который как раз void* обычно и является.
S>>Казалось бы, в твоем распоряжении инструмент, который позволяет забесплатно и автоматически снять с тебя нехилый кусок головной боли. S>>Но ты от этого отказываешься, да еще и кичишься этим.
Pzz>Сколько лет ушло у линуксячего ядра, чтобы наконец вычистить предупреждения? (да и то я не уверен, что их вычистили целиком).
Меня не интересует ядро Linux-а, тем более, что это пример проекта без дедлайнов и с неограниченными ресурсами.
Pzz>В таких задачах люди типа даже не Альфы (про него, живого, мы мало чего знаем), а описанной вами чуть выше модели альфы вполне могут работать.
Могут. Только если в таких задачах намечается тенденция к росту кодовой базы, то взгляды персонажей вроде Альфы очень быстро приводят ее в состояние говнокода.
Здравствуйте, serg_joker, Вы писали:
_>>>Убедил, всеми силами буду стараться держаться от него подальше Pzz>>А куда ты денешься, PDF использует евонные кодеки. _>Я имел ввиду работу с библиотекой как программист.
Других для C/C++ нет. Если понадобиться об TIFF мараться, придётся с этой.
Здравствуйте, so5team, Вы писали:
Pzz>>Не, ну это всё же специально стараться надо. Случайно так не ляпнешь.
S>Да сколько угодно как только народ начинает пропихивать информацию через void*. S>Например, если есть callback-и с дополнительным параметром userData, который как раз void* обычно и является.
Хех. Вы не застали времена, когда в UNIX было принято пропихивать информацию через unsigned int.
На VAX-е то он был 32 бита, как и указатель.
Я в те времена писал под MS-DOS. Unsigned int для меня был 16-битным, а указатель, в large модели — 32-битным.