Как стать автором
Обновить

Комментарии 68

образование в ведущем ВУЗе вообще не гарантирует, что человек умный

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

В программировании все индивидуально. Образование важно для страта, но дальше важнее практика и желание копаться с мелочами. Лично видел как по-разному подходили два программиста к коду. Один писал как учили в ВУЗе, а второй писал по функциональности, что требовало дополнительного описания ибо не сразу можно было «вкурить»)), но читать его код было одно удовольствие.

Да, все индивидуально:

Обучение началось с изучения систем счисления. Всё что я знал до этого
момента про счёт – это арабские и римские цифры. А оказалось, что в
повседневной жизни мы пользуемся десятичной системой счисления, а вот
для электронно-вычислительных машин это совсем не подходит и в них
используется двоичная система счисления, состоящая из нулей и единичек. А
ещё есть восьмеричная система счисления от 0 до 7 и даже
шестнадцатеричная от 0 до 9, а далее A, B, C, D, E, F. Последняя система
вводила в ступор: символ «А» это же буква, а не цифра! О, сколько
усилий пришлось приложить, чтобы мозг соотносил цифру 10 с буквой, с
символом «А» при восприятии предложения «шестнадцатеричная цифра A» и
т.д.

И всех, конечно, с наступающим Новым Годом!

Счастья и удачи, друзья! Творческих успехов!

Ответ на вопрос "Почему некоторые люди склонны к магическому мышлению?" можно найти в модели спиральной динамики. Люди, для которых основным уровнем является пурпурный (или фиолетовый) будут верить в магию. До тех пор, пока не разовьют в себе вышестоящие уровни.

Рекомендую к изучению. Помогает в понимании явлений

Поясняющий текст картинкой.

P.S. Так что это не показатель глупости, а показатель развития человека в рамках данной модели.

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

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

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

Все же понимают что так не должно быть, а "шаманизм" здесь не причем? Взять кого угодно, приставить пистолет к виску и сказать - "Меняй этот код! Будет работать, тебе ничего не будет. Не будет - сам виноват..." Готов спорить если известно, что код худо бедно работает вы внесете в код самые косметические изменения... Что собственно и произошло.

Если подробнее разобрать кейс то одна из проблем нежелание, неумение писать комментарии. Напиши "сделано не правильно по тому-то, почему правильно не работает хз, может ошибка в компиляторе, не разбирался - нет времени. Так тоже работает."

Даже будучи не программистом сталкивался - пишешь на бейсике для микроконтроллера, вроде все правильно. А железяка не просыпается как положено. Копаешь документацию к баскому - все у тебя верно. Копаешь документацию к МК - все верно. Но не работает. Идешь в гугл - на 5 странице какого-то форума совет сделай все наоборот. Делаешь - все работает как часы... Ну ладно, написал комментарий на будущее и забыл, все равно у меня нет ни времени ни квалификации разбираться с компилятором.

он где-то слышал про "проблему машинного нуля", когда x+1. == x, если x>>1 или x+1.==1., если x<<1 ( "<<" соответстует тому, что 1 и x одновременно не помещаются в мантиссу представления floating poing IEEE-854(?), если привести их к одинаковой экспоненте перед сложением).

И вот, он "слышал звон", и не знает, где он.

Этому обычно на 1 курсе учат, что числа floating point нужно сравнивать только так:

#define Epsilon 0.0000001

...

if (fabs(x-y)<Epsilon) {...}

IEEE-754.

Вы отличный пример того, о чём я писал. Написали фантастическую чушь и получили уже 4 лайка, причём не от девочек комсомолок, а от людей на техническом ресурсе. Никогда, слышите, никогда, не вставляйте в программы это говно! Если вам нужно сравнить два числа, просто пишите if (x == y). Арифметика чисел с плавающей запятой сама правильно проверит, равны они или нет. Ваш же говнокод будет давать результат, что один нанофарад равен одному пикофараду. Людям, расчитывающим паразитные ёмкости процессора в вашем компьютере, такой результат очень не понравится!

Если вам нужно сравнить два числа, просто пишите if (x == y). Арифметика чисел с плавающей запятой сама правильно проверит, равны они или нет.

Тут недавно был интересный трюк, когда условно 5/3 были не равны 5/3 иногда, при этом бинарно значения совпадали. Так что if x==y не всегда корректно сравнивать. А вообще сравнение чисел с плавающей запятой на равенство - отдельная дисциплина специальной олимпиады :)

когда условно 5/3 были не равны 5/3 иногда, при этом бинарно значения совпадали

А это как вообще O_0? Где про это «недавно» можно почитать?

Вот тут https://habr.com/ru/articles/754730/ . Оказалось, компилятор один из операндов сравнения оставил на FPU x86 в 10-байтном регистре, а второй лежал в памяти с размером double. Сравнение также выполнялось в размере 10 байт и естественно провалилось, так как 8-байтовый double дополнился нулями.

Хм, заставили задуматься, но нет, не везде одинаково работает. Такой код на С:

float a = 10.0 / 3.0 - 3.0;
float b = 2.0 / 6.0;
if ( a==b ) ....

Действительно считает и сравнивает корректно. Но, например в PHP и Python вычисленные значения будут отличаться:

0.3333333333333335
0.3333333333333333

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

Тут зависит от оптимизаций - компилятор мог всё сам посчитать, поэтому надо часть значений передавать как внешние к программе, тогда компилятор не сможет просто выкинуть эти все вычисления и заменить результатом. Ну и см. ниже про -ffast-math.

Никогда, слышите, никогда, не вставляйте в программы это говно! Если вам нужно сравнить два числа, просто пишите if (x == y). Арифметика чисел с плавающей запятой сама правильно проверит, равны они или нет

Если нужно сравнить два числа, то да. Но обычно нужно сравнивать две величины. Заданные или расчитанные с определённой точностью.

Ваш же говнокод будет давать результат, что один нанофарад равен одному пикофараду.

Ну, а ваш говнокод покажет, что 5 фарад не равны 5.000000001 фарад. Формально они не равны, но кого это волнует?

Людям, расчитывающим паразитные ёмкости процессора в вашем компьютере, такой результат очень не понравится!

Как обращаться с погрешностями учат если не на первом, то на втором курсе любого инженерного вуза. Советую поинтересоваться. Там подробно эту проблему показывают и рассказывают.

Вот по ссылке статейка, где автор показывает, что оба ваши подхода неверны.

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

static const double expected = 1. / 3. + 1;

int main() {
double num;
std::cin >>num;
std::cout << (num / 3. + 1 == expected);
}

Компилирую на intel/amd с 'gcc -ffast-math -O2'. Передаю '1' в програму - получаю результат - не равны. Что я делаю не так?

Это не магическое мышление, это просто недостаточный опыт в программировании при большом (наверное) опыте в математике.

Когда я рефакторю малознакомый код на десятки или сотни тысяч строк кода, у меня тоже главная задача — ничего не сломать. Даже если вижу где‑то треш, угар, содомию и рекурсивное вычисление ряда Фибоначчи, я всё это игнорирую и фокусируюсь на одном конкретном пункте рефакторинга.

P. S. Магическое мышление — это переобученность человеческой нейронки.

Это не магическое мышление, это просто недостаточный опыт в программировании при большом (наверное) опыте в математике.

Наоборот: это достаточный опыт в программировании что бы осознать пользу принципа "Работает - не трогай".

«Работает — не трогай» — это не магическое мышление.

Сейчас все модели сломаются! Потом скажут, что мы всё сломали! Я такие изменения не пропущу!

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

x = (a + b * c + d) * (g - sin(alpha) * cos(beta) ) * (cos(d5) + d8 + d11) / (k - t * p) / (d7 + d9 + d15);

y = (a + b * c + d) * (g - sin(alpha) * cos(beta) ) * (cos(d5) + d8 + d11) / (k - t * p) / (d7 + d9 + d15);

z = (a + b * c + d) * (g - sin(alpha) * cos(beta) ) * (cos(d5) + d8 + d11) / (k - t * p) / (d7 + d9 + d15);

Не напрягая мозг я бы сказал что это какие-то проекции.. Может быть в какой-то другой "системе координат" какие-то проекции нужно считать по разному. Поэтому 3 строчки. На всякий случай, вдруг придется поменять. Иначе почему не пойти дальше: выкинуть на фиг у и z, оставить один х )))

Компилятор прекрасно справится с тем, чтоб делать только одно вычисление. А может у них в кодстайле запрещено писать x = y = z, мало ли по каким причинам.

Нам как-то раз в наследство достался древний проект на железе. Это была такая боль, что некоторые паттерны оттуда мы внесли в кодстайл в раздел "никогда, слышишь, НИКОГДА, так не делай". Потому что сейчас ты гордишься своими трюками с языком, а через 5 лет люди будут посылать тебе лучи поноса, пытаясь понять что ты там хотел сделать.

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

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

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

Что касается "мистики" в коде, то, вот, в Питоне есть, например, такие фокусы:

>>> Decimal(0.1)

Decimal('0.1000000000000000055511151231257827021181583404541015625')

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

В приснопамятном Борланд паскале разлива девяностых иногда добавление строчки комментария в код исправляло компиляцию. Сколько таких хвостов в NUMA-кластере, у которого пользовательская база весьма ограничена, даже подумать сложно.

Опять же, очень часто, способный новичок, особенно, ортогональноголовый, недооценивая деталей задачи и не обладая необходимым жизненным опытом, чтобы эти детали предвидеть, полагает, что всё можно запрограммировать непротиворечиво. Смущает своими речами коллег, берётся переделывать и... стабильно увязает через 2 месяца, когда всё логичное уже сделано и мы подходим к самому интересному, обнаруживаем, например, что некорректные входные данные нельзя терять, а способов, которыми они некорректны слишком много. Если такому тимлид своевременно не настучит по голове, то это будут выкинутые трудодни.

В общем, свежий продвинутый взгляд на код всегда полезен, но далеко не всегда бывает верен :) А с другой стороны, чистых мистиков в программировании тоже хватает. Тут, скорее, по результату нужно смотреть. Если продукт есть, если он приносит прибыль, значит модель и команда выбраны верно, что бы нам не говорило чувство перфекционизма. Когда бизнес занеможет - кто то это перепишет и сделает новый бизнес.

P.S. А за книжечку спасибо. Хорошего Нового Года!

В приснопамятном Борланд паскале разлива девяностых иногда добавление строчки комментария в код исправляло компиляцию.

И в Си бывало...

Это как?

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

Помню веселье с часами отладки в попытке понять, почему код выводит стабильно неправильные значения на простейшем куске программы (а вот что именно там надо было считать уже не помню). В итоге с привлечением мега-спеца из соседнего отдела и ковырянием в ассемблерном коде (дело было на С++) выяснилось, что это компилятор тупо генерит неправильный бинарный код для какой-то простейшей арифметической операции.

Любое изменение структуры файла (просто перестановка местами пары методов выше по коду, даже не тех в которых была проблема) баг убирало. Баг вроде зарепортили.

Такое тоже может быть, и не так уж и редко.

некорректные входные данные нельзя терять

Что Вы имеете в виду?

Например, нужно вкачать фио/адрес, адрес увязать с КЛАДРом. Ну и ещё ворох таких же источников и хотелок. Казалось бы, что может пойти не так, если первичку вводили живые люди?

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

Потом приходит юный отличник, смотрит на вот это и начинает сердиться: "кто так строит? всё должно на всё ссылаться, нужно всё переделывать!". А поскольку это такие вещи, что если надо объяснять, то не надо объяснять, то ему один раз ответят, а дальше ждут, что он будет что-то полезное делать и живого опыта набираться.

Конечно, бывают такие проекты, что там не спроектированный бардак, а просто бардак. Но разраб без опыта отличить не сможет.

Вот так, самые светлые намерения рассыпаются о суровый быт. :-(

Избыточно много ругани в адрес других людей. Есть ощущение, что автор подсознательно самоутверждается в стиле "ну бараны, ну как такое можно с высшим то образованием то, вот я бы, вот я бы, такого НИКОГДА!... ". Возможно есть какая-то книга по психологии или антропологии, где описывается механизм в психологии, когда человек переоценивая известное **лично ему начинает оценивать окружающих исключительно по этой области знаний.

Хабр меня спросил, одобрить Ваш комментарий или нет. Я одобрил, чтобы Вам полайкали люди, поддерживающие идею, что неправых нет, все немножко правы, и что в соревновании все немножко победители. Помните, как в фильме "Парни со стволами"? "Они вручили трофеи всем, чтобы никто не обиделся. Даже жирному тупице Роби Фридману дали." p.s. Программирование, как и точные науки, раньше отличалось от уроков литературы тем, что была чёткая грань между правыми и неправыми. Сейчас она размывается всё сильнее.

Обратите внимание, я сейчас ещё и страдаю за свою объективность к оппонентам)) Вам плюсуют, а мне уже кто-то заминусовал сообщение о том, что я допустил Ваш комментарий.

Примите Хабр таким, как он есть и перестаньте страдать! Карма тлен, а уж плюсы к комментам, так и подавно...

Позвольте предположить, что лет через 10 уважаемый автор станет руководителем и будет отвечать за продукт и множество проектов :). И тогда ему тоже не понравятся изменения в работающем коде, только потому что его действительно умный и цепкий программист не доволен манерой автора. Уверен, что вспомнив сегодняшнюю статью, уважаемый автор найдет правильные слова, чтобы объяснить разработчикам, что просто так не стоит улучшать , что и так работает :).

Я вообще очень опечален, что, судя по комментариям, никто не понял, что я хотел донести. Но я отвечу на Ваш вопрос. Принцип не трогать работающий код обычно является следствием непонимания того, как что-то работает. Именно поэтому я считаю такой принцип дерьмом. Если компания работает по этому принципу, значит она движется вперёд просто по инерции. В какой-то момент количество точек непонимания превысит критическую отметку и всё посыпется как карточный домик. На том же месте работы у меня был опыт, когда доказать необходимость изменения кода логическими объяснениями того, что движок написан неправильно, ни к чему не привели. Тогда я написал модель и добавил её в список тестов. Моя прекрасная модель рушила движок просто фантастически. На каких-то машинах программа просто валилась, на каких-то намертво вешала систему. Было приятно смотреть, как все забегали. После этого необходимые изменения прошли на ура. Так что я надеюсь, что если и когда я стану руководителем, я буду слушать вменяемых людей, а не жить по принципу "давайте не раскачивать лодку".

Я вас очень хорошо понимаю. И в любом большом куске кода найдется немало таких забавных примеров. В моем понимании это результат трудности коммуникации и спешки. Эти два фактора присутствуют в любом проекте. Плюс всегда есть история вопроса. Итого мы видим как организм из нескольких умных и талантливых людей не всегда ведёт себя рационально. И как с этим быть не всегда ясно. Бизнес задачи в приоритете, а любое изменение кода имеет ненулевую цену. Особенно если это изменение затрагивает двух человек. А не дай бог им потребуется арбитр , тогда цена легко может оказаться равна тысячам условных единиц :).

У несчастью, мне регулярно приходится сталкиваться с кодом, который непонятно как работает, и это не вина пишущего. Такое бывает, например, если имеете дело с ворохом 3rd party зависимостей, причём требуется какая-то конкретная комбинация из версий, и везде свои баги. Эмпирически вы знаете, что такая последовательность вызовов работает, а другая - нет, причём из документации не следует ничего. Получается, что даже автор ничего вменяемого в комментариях написать не может, кроме "не трогай, должно быть так".

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

Не станет. Задача руководителя продать говно и закрыть проект. А не нудеть, что надо всё переписать

изменения в работающем коде

Это не работающий код, а работающий говнокод. Я вполне понимаю, что несколько присваиваний в одном выражении может не нравиться (мне оно тоже не нравится), но можно же вместо трижды копипаста строки длиной в полторы ширины экрана присвоить сначала её результат в какую-то еще одну переменную, а потом её уже присваивать по очереди в x, y, и z. Может, правда, у них какая-то особая реализация синусов и косинусов, которая имеет значимые побочные эффекты - тогда и вправду лучше не трогать (а если, все-таки, трогать, то только метров с пяти длинной палкой).

мол если множитель равен 1, то лучше не умножать, потому что это может изменить умножаемое число, если это число мало. Писал, очевидно, человек, который не знает, что в представлении с плавающей запятой числа хранятся так, что их относительная точность не зависит от того, равно число 1.e+100 или 1.e-100.

Знание того, как оно хранится, не поможет. Тут надо знать алгоритмы выполнения операций в плавающем формате, чтобы сделать цепочку выводов:

  • При умножении нет выравнивания порядков и связанной с этим потери точности

  • Нет потерь точности на представление единицы (как константы, а не как результата вычислений) в плавающем формате. Она хранится абсолютно точно.

  • При умножении результирующая экспонента = сумме экспонент, но у единицы она нулевая, а значит экспонента результата не изменится

  • Представление единицы имеет одни явные нули в мантиссе. Но есть одна неявная старшая единица. Именно она и гарантирует сохранение абсолютно всех знаков мантиссы другого сомножителя в старших разрядах результата. Ну а нули гарантируют обнуление всех остальных (младших) знаков мантиссы результата

  • Таким образом, мантисса результата абсолютно не изменится

  • Знак результата не изменится

  • При применении одного и того же алгоритма умножения для всех плавающих чисел, и даже при выполнении реальных вычислений, умножение на единицу никак не изменит исходное число. Даже на epsilon. Вообще ни на сколько.

  • Вот такой фокус

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

И это оказало некоторое воздействие на систему. Вы же сами хотя в одном месте пишете сначала это

эта проверка является совершенно бессмысленной, хоть и довольно безвредной 

а затем вот это

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

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

Ваши колеги чувствуют магию, а вы ещё нет ;) Если вы используете x86+ процессоры, то есть такое понятие как extended precision floating point (80 bit).

https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format

Процессоры интел (и иже с ними) делают операции с расширеной точностью, но компиляторы обычно пытаются избавится от этого и использовать стандарт IEEE-754 для вычислений, за исключением случаев где их просят этого не делать (gcc флаг -ffast-math). Вот пример кода:

#include <limits>
#include <cmath>
#include <iostream>

int main() {
double num;
std::cin >>num;
double mult = num / (pow(2, 54)) - 1;
double factor = 2;

if (fabs (mult - 1.) > std::numeric_limits::epsilon ()) {
factor *= mult;
}
std::cout << num << " " << mult << " " << (factor + 2) << std::endl;
}

Если скомпилировать с:
g++ -o math math.cc -ffast-math -O2

и передать в программу 1 то результат будет разный с этой проверкой и без неё.

Число передаётся как параметр, чтобы избежать оптимизации компилятора, который тогда всё сам посчитает.

С проверкой выдаёт 0, а без 1.11022e-16.

g++ -o math math.cc -ffast-math -O2

А так точно можно?

Нельзя
Нельзя

std::cin >>num;

Что вводите сюда?

С проверкой выдаёт 0, а без 1.11022e-16.

Для какой переменной?

Я вроде в оригинальном сообщение сказал что передавать надо 1. Смотреть надо на последнее выводимое число, так как только оно зависит от того добавлен ли if или удалён.

Вы будете удивлены сколько проектов используют -ffast-math. Дело в том что есть SIMD инструкции процессора и инструкции типа fmuladd которые компилятор не имеет права использовать без нарушения точности IEEE-754. Буду весьма удивлен если ваш проект не использует -ffast-math.

сказал что передавать надо 1.

Математика Ваша не бьется, поэтому и спрашиваю.

Равно 4. Не ноль и не 1.11022e-16
Равно 4. Не ноль и не 1.11022e-16

В принципе, мне всё равно.

Вы будете удивлены 

Удивлен. Даже подпись на картинке имеется - а вам всё равно непонятно.

Мда, хабр сжевал double в std::numeric_limits<double>::epsilon() не знаю как у вас компилируется этот код.

$ g++ -o math math.cc -ffast-math -O2 && echo 1 | ./math
1 -1 0

Комментируем проверку:

$ g++ -o math math.cc -ffast-math -O2 && echo 1 | ./math
1 -1 1.11022e-16

Ладно, будем считать что мне не удалось продемонстрировать вам удивительный мир floating point на архитектуре x86.

Вы бы код посмотрели, что там накомпилировалось. Если скриншот правильный, то может просто в коде UB и вы совершенно случайно получаете то, что хотите получить

А так точно можно?

Так речь же о том, что опция -O не должна включать -ffast-math, потому что это изменяет результат вычислений. Типа, если вам надо, включайте ее осознанно и отдельно.

потому что это изменяет результат вычислений.

потому что это приводит к неверным вычислениям

Нет, это изменяет результат. "Неверность" или "верность" вычислений определяется требованиями к ним.

@ivanrtиспользует опцию "-o" (output file), а не "-O" (optimization level).

Он использует обе. Релевантная даже жирным выделена

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

if (fabs (mult - 1.) > std::numeric_limits::epsilon ())

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

Извините, если это выглядело как травля или что-то такое. Согласен, с вашими рассуждениями и то что полагаться на мусор в последних разрядах числа это неправильно, поэтому как раз обычно используют epsilon при сравнениях, который вы активно отвергали в другом обсуждении. То что сделал ваш коллега-програмист очень похоже на poor-man's -fno-fast-math в данном куске кода - отрезать мусор, но в очень специфической ситуации, чтобы залатать проблему не желая разбираться в первопричинах. Вполне человеческое желание, как и желание начальника случайно ничего не сломать, так как нет полного понимания как это всё работает. Желаю вам найти понимание с коллегами или может других коллег. Я как бульдог, сначала я готов был с вами согласиться в вашей оценке ситуации, но заметив эту интересную особенность в коде вцепился в неё забыв об остальном.

О, хорошо сформулировали, именно "полагаться на мусор в последних разрядах". И коллега, как я и писал, просто залатал проблему - неработавший код, который, который после его изменений, стал падать немножко по-другому, введением этой магии стал снова падать старым способом, тесты стали показывать, что всё хорошо - всё ломается так, как ломалось раньше - и все успокоились.

Вы, кажется, не поняли, что умножение происходит не на единицу

не важно, происходит умножение на 1.00000000000000 или на 1.000000000000001. если поведение программы зависит от этого, значит где-то в ДРУГОМ месте программы, либо во входных данных, имеется ошибка.

Выходит так, что автор, несмотря на свой опыт в программировании ни разу не словил глюка от причуд компилятора? Кучу времени может иногда потратить даже чтобы понять что именно не так со строчкой "2+2", с копанием на уровне асма. Компилятор взял, оптимизировал - убрав вообще "ненужный" кусок кода. И что оно там должно да обязано тогда уже никого не волнует, надо чтоб работало.

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

Сейчас все модели сломаются! Потом скажут, что мы всё сломали! Я такие изменения не пропущу!

Ни в коем разе не оправдываю группенфюрера, который не въехал в то, что делает код...

Но сломаться может что угодно, где угодно и как угодно.

Пример из жизни: как-то я выкинул кусок легаси кода, результаты которого нигде не использовались. Ошметки многократно измененного алгоритма. Мусор. Причем, я же опытный индеец, перед этим покрыл код юнит тестами. Ну вообще ничего не должно было сломаться.

Тестирование прошло успешно.

А потом все стало сыпаться на проде в совершенно левых местах. На тестовой среде не сыпалось.

Стоило отката системы к предыдущему релизу и многих седых волос.

Разгадка оказалась следующей: в совершенно других местах было криво реализована синхронизация потоков. Этот легаси, который я почистил, добавлял задержку на несколько мс. За это время другой поток успевал доделать работу, и потом, текущий поток мог брать уже готовые данные. А без легаси другой поток не успевал доделать, и текущий поток хватал неконсистентные данные. На проде. А на тесте ядер было поменьше, степень параллелизма кое-где отличалась и все выполнялось чуть иначе.

Можно сколько угодно говорить, что код - Г, что авторов найти и надавать канделябром по пальцам, что во всем этом надо разобраться и все переписать.

Но факт остается фактом: выкинул ненужный код - все упало.

Я над тем проектом давно не работаю.

Но всегда перед релизом ввожу не только фича-фриз, но и рефакторинг-фриз. Рефакторинг - только в первую неделю спринта. Сложный рефакторинг - только при наличии ценности для бизнеса, при наличии "воздуха" в спринте, при возможности для него 1-2 спринта "отлежаться" на препроде.

И пусть меня считают глупым душнилой и тормозом прогресса.

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

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

Позиция тимлида обязывает сидеть в технике только одним полупопием, а вторым сидеть в бизнесе.

Поэтому, фокус на том, чтобы 1) команда прогнозируемо поставляла ценности бизнесу сейчас. 2) команда поставляла бы ценности бизнесу в будущем не хуже (в идеале - луче), чем сейчас

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

Особенно боялся бы трогать, если бы писал софт для марсохода.

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

Если с шашкой наголо набрасываться на говнокод, то результат получится обратный: дестабилизация решения, срыв сроков. А если это делать слишком рьяно, то возможен провал проекта.

Я не к тому, что говнокод надо терпеть. Как написал выше, умеренный рефакторинг вполне допустим задолго до релиза и если есть время, чтобы успеть стабилизировать решение. И допустим он только тогда, когда выгода от рефакторинга в будущем явно выше потенциального вредв в настоящем.

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

Вот представьте, пришли вы к стоматологу с больным зубом, а он вам удаляет, ставит протез, и говорит: с вас 100500 денег. Хотите попасть в такую ситуацию? Я вот - не хочу.

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

Всё равно остаюсь при мнении, что выкинутый вами легаси вскрыл проблему, которая могла вылезти в другом месте. И благодаря тому, что вскрыли её ваши действия, вам было проще найти ошибку. Она бы всё равно вылезла, рано или поздно. У какого-нибудь пользователя, который потом писал бы вам в поддержку. Тупорылые прокладки между пользователем и разработчиком пытались бы конечно её решить, но вряд ли решили бы, и пока она дошла бы до вас, пользователь вас бы возненавидел. Так что плюс вам однозначно.

Надеюсь, вы не только тормоз прогресса, но еще и выдаете вашей команде эти самые 1-2 спринта на регулярные рефакторинги.

Автору совет - забейте. Все кругом вас пишут говнокод и всех это устраивает - ну так и вы делайте то же самое. Своей борьбой за качество вы ничего не добьетесь кроме собственного выгорания. А еще лучше - уходите из программирования вообще. Практически вся разработка скатилась на днище, и ломится чтобы его окончательно пробить. В медицине, юриспруденции, или, например, авиации вас даже близко не подпустят к работе без сотни (хотя бы формальных) подтверждений компетенций. А в программировании вчерашний развозчик шавермы на самокате будет вам сегодня втирать "алгоритмы не нужны", "образование - зло" и т.п., а вы, вместо того чтобы просто послать идиота на хер будете вынуждены на полном серьезе с ним дискутировать, безрезультатно тратя свое время и нервы. Врачи тоже, конечно, бывают разной компетенции, но как-то сложно представить ситуацию, что какой-то врач на работе начнет загонять, что гонорею надо лечить припарками из листа подорожника и с ним всерьёз будут это обсуждать. В программировании выбор это либо влиться в общую струю говнища, получать спокойно свою з/п, и после 40-45 лет стать никому не нужным говнокодером, либо, как вы, пытаться что-то изменить вокруг себя, ничего в итоге не добиться, заработать хроническое утомление, и после 40-45 лет стать никому не нужным говнокодером. Хотя, вообще-то, есть, все-таки, и третий вариант - это иметь хорошее образование и подготовку в какой-либо очень специфичной области, и в ней работать, но он не всем и всегда доступен, потому что об этом надо думать и над этим надо очень сильно работать начиная еще со студенческой скамьи.

Согласен с поиском специфичной области, сам пришёл к этому выводу буквально пару лет назад. Сейчас работаю в навигации, тут ошибка в микросекунду даёт ошибку в дальности в 300 метров, поэтому долбанько тут сложнее)

Для меня что-то околонаучное уже поздно. Думаю к концу года уйти на 1С. Там хоть (надеюсь) даже на старости хоть какой-то кусок хлеба будет.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории