Я читал статью о плохих практиках программирования .
Это упомянуто -
«Код Yo-Yo», который преобразует значение в другое представление, а затем преобразует его обратно в исходное положение (например, преобразование десятичного числа в строку и затем обратно в десятичное, или заполнение строки и затем ее обрезку)
Я не понимаю, почему конкретный пример, который он приводит, - плохой способ написания программ. Мне кажется, можно конвертировать обратно, если того требует ситуация, чтобы можно было использовать это значение.
Кто-нибудь может объяснить больше об этом?
programming-practices
anti-patterns
user13107
источник
источник
"Roundabout code" that accomplishes in many instructions what could be done with far fewer (eg: rounding a number by converting a decimal into a formatted string, then converting the string back into a decimal)
.if the situation is so that they have to be used?
- что это будет за ситуация?decimal myValue = decimal.Parse(dataReader["myColumn"].ToString())
моя любимая мозоль.Ответы:
Даже если вы делаете потребность как числовой и строковое представление числа, то лучше конвертировать только один раз , а также повесить на исходное значение, вместо того , чтобы снова преобразовать каждый раз , когда вам нужно один или другой.
Принцип, как всегда, в том, что код, который не существует, не может иметь тонких дефектов , в то время как код, который существует, часто имеет. Это может показаться параноидальным, но опыт учит нас, что это уместно. Если вы подходите к программированию с постоянным легким беспокойством «я не настолько умен, чтобы понимать эту сложную систему», вы на правильном пути.
источник
Это плохо по трем основным причинам:
Я подозреваю, что причина 1 - это причина, по которой ваш источник размышлял, исходя из контекста, в котором он был упомянут.
источник
Я бы перефразировал описание как «код, который преобразует тип в другое представление с целью сделать что-то, что можно было бы сделать так же хорошо или лучше в оригинале, а затем преобразовал бы его обратно. Есть много ситуаций, когда преобразование чего-либо в другой тип, действующая на него, и преобразование его обратно вполне уместно и неспособность сделать это может привести к неправильному поведению.
В качестве примера, где преобразование является хорошим: у
каждого есть четыре
float
значения произвольных знаков, величины которых могут различаться с коэффициентом до 1000, и необходимо вычислить сумму с точностью до 0,625 единиц в последнем месте. Преобразование всех четырех значений вdouble
, вычисление суммы и обратное преобразование результатаfloat
будет гораздо более эффективным, чем любой другой подход, использующийfloat
один.Значения с плавающей точкой в лучшем случае с точностью до 0,5 единиц в последнем месте (ULP). Этот пример потребует, чтобы ошибка округления в худшем случае была не более чем на 25% выше оптимальной ошибки в худшем случае. Использование double даст значение, которое будет точным в пределах 0.5001 ULP. Хотя требование ULP 0,625 может показаться надуманным, такие требования часто важны в алгоритмах последовательного приближения. Чем точнее указана граница ошибки, тем ниже требование к итерациям в худшем случае.
В качестве примера, где преобразование плохое:
один имеет число с плавающей запятой и желает вывести строку, которая будет уникально представлять его значение. Один из подходов - преобразовать число в строку с определенным количеством цифр, попытаться преобразовать ее обратно и посмотреть, соответствует ли результат.
Но это на самом деле плохой подход. Если десятичная строка представляет значение, которое почти точно находится на полпути между двумя значениями с плавающей запятой, для метода строки-с плавающей запятой довольно дорого гарантировать, что он всегда будет давать более близкое
float
значение, и многие такие методы преобразования не не поддерживать такую гарантию (среди прочего, в некоторых случаях для этого потребуется прочитать все цифры числа, даже если длина его составляет миллиарды цифр).Для метода намного дешевле гарантировать, что он всегда будет возвращать значение, которое находится в пределах 0,5625 единиц на последнем месте (ULP) от представленного значения. Надежная «обратимая» процедура форматирования десятичных чисел в строку должна вычислять, насколько далеко выходное значение от правильного значения, и продолжать выводить цифры, пока результат не будет в пределах 0,375 (ULP), если не 0,25 (ULP). В противном случае он может вывести строку, которую некоторые методы преобразования будут обрабатывать правильно, а другие методы преобразования - нет.
Иногда лучше вывести цифру, которая может не быть «необходимой», чем вывести значение, которое может быть неправильно истолковано. Ключевым моментом является то, что решение о том, сколько цифр должно быть выведено, должно приниматься на основе численных расчетов, связанных с процессом вывода, а не в результате попытки одного конкретного метода преобразовать строку обратно в число.
источник
Разные причины
Это бессмысленно и добавляет сложности - как в объеме кода для написания и поддержки, так и в количестве необходимого процессорного времени
Он может потерять точность или, что еще хуже, полностью испортить ценность
Это тратит впустую память (потенциально, в зависимости от языка), поскольку вы в конечном итоге сохраняете больше представлений нужного вам числа
Хорошей практикой является сохранение только первого, наиболее точного из возможных представлений для любых данных, которые вы получаете. Выполните любые вычисления, используя эти данные, и конвертируйте их только в том случае, если вам нужно вывести их или отобразить в более удобном для чтения формате.
источник
Зачем? Потому что даже лучшие из нас могут ошибаться.
Посмотрите, что произошло, когда Microsoft попыталась внедрить формат «туда-обратно» специально для того, чтобы убедиться, что преобразования с плавающей запятой <-> были безопасными: https://stackoverflow.com/q/24299692/541686
источник
Когда я был в школе (и после школы в области электротехники), нас учили делить после умножения. Деление часто многозначно и округляется. Умножение после деления умножает ошибку деления.
Преобразования типов одинаковы, вы рискуете потерять данные. CInt (1.3) = 1.
На моем языке Basic мы выполняем только преобразования типов (программа VB6 тратит 90% своего времени на преобразование ANSI / Unicode для всех вызовов API, выполняемых средой выполнения).
Преобразование типов подразумевается во всем, что мы делаем.
Строка «5» печатается из числового литерала.
Строковый литерал Юникода преобразуется в строку ANSI и отправляется в SetWindowsTextA пакетом форм.
Даже это работает в основном
Сейчас я программист по вариантам - я даже не думаю о типе. Я просто полагаюсь на автоконверсии.
Во всяком случае, мои 3 любимые мозоли
Назначение строковых литералов переменным для их использования (тратит память и медленно)
Бессмысленные функции, когда код может быть встроенным (и компилятор, вероятно, отменит вашу функцию и встроит ее в любом случае)
Установка всех объектов в ноль в качестве последних строк перед функцией завершения или концом программы.
и четвертый для коротких программ
Бессмысленно диммируя ваши 3 переменные в 5-строчной программе.
источник