- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
static void Main() {
Random random = new Random();
...
int n1 = notations[random.Next(max)];
int n2 = notations[random.Next(max)]; // дублирование кода!
....
//исправлено на
int n1 = notations[random.Next(max)];
int n2 = n1;
}
вообщем что я хочу сказать: рандомные числа они не есть неизвестные, они есть непознаваемые.
неисповедимы пути рандомов.
Ну поэтому эти числа и называются псевдослучайными.
типа: почему они псевдо?! они ведь на самом деле случайные и не предсказуемые!
UPD: А тьфу. Это за даблпост. Сорри. Инет лагал. Думал один раз запостил.
У нас с тобой очень разные интуиции...
Заонанировали уже использования знака копирайта в таком уродливом виде, да ещё и не к месту.
ага, чтобы вы не дайбох подумали, что это я про себя )
Люсидфокс же.
> использования знака копирайта
Провослабный знак для цитаты - (q), жаль, не стандартизуют.
Что-то типа ⓠ.
Кощунитесь над православными?
Видимо код проектировался с участием Чурова...
Пруфпик: http://rghost.ru/40288588.view
Наведите курсор вот сюда, что бы убедиться:
http://govnokod.ru/1#comment3
а после, ознакомиться с
https://ru.wikipedia.org/wiki/Генератор_псевдослучайных_чисел
>static void Main()
Подозрительно.
Сам код уже реализован несколько располагающе к таким выводам (что идет дубликат кода), потому что код действительно визуально воспринимается как дубликат и только random выдает все хитросплетения коварства автора.
Требовалось добавить комментарий о том, берем два рандомных значения, пусть это и комментарий капитана, но зато остановило бы от подобных правок, тех кто читает код на автопилоте :).
А на самом деле - ну каким надо быть идиотом, чтобы изменять вызов функций, не ознакомившись с тем, имеют ли они побочный эффект?
Так и до такого маразма недалеко:
Две крайности: функция #11712 и РГМ.
Один из симптомов воспаления рефакторинга в заплаточной форме -- пренебрежение документацией.
А в защиту рефакторинга скажу, что Фаулер что при рефакторинге, что при оптимизации архитектуры советовал понимать, где проходят границы текущей подсистемы, т.е., что мы можем ковырять, а что является внешним и может нести побочные эффекты. Даже не залезая в доки и другой код ясно, что Random - вне подсистемы. Может быть, notations[что-то] тоже вне подсистемы.
Исправление коснулось внутренней структуры кода: было две разных переменных -- стало две одинаковых.
Вопрос о том, что нужно читать документацию к коду, с которым работаете, НИКАКОГО отношения к Фаулеру не имеет.
Исправление изменило побочные эффекты кода - поэтому оно ну никак не могло остаться внутренним для подсистемы.
> Вопрос о том, что нужно читать документацию к коду
И желательно ее еще и писать, хотя лень ;)
Внешнее тут вообще ни при чём: контракты соблюдены, сторонних делегатов в main не передавалось.
К тому же... Random внутренний объект. Notations не изменялся.
По сути это заведомо гомоморфизм внутрь идеала, где random выдаёт всегда два подряд одинаковых числа. Код не изменился ВООБЩЕ!
Вы всегда говорите так много умных слов, сочетание которых превращается в неведомую ту самую.
Кстати, в каких книжках по ПО нынче пишут про "точки инверсии"?
Я не сказал, что не надо читать доки.
Надо стараться не просто не вызывать побочных эффектов у внешних подсистем. Надо стараться видеть, где у тебя границы проходят, чтобы, с одной стороны, минимизировать число вызовов между границами, с другой стороны, и не изменять вызовы так смело, без изучения внутренностей других подсистем.
А Фаулера вспомнил, потому что тут упоминали рефакторинг и потому что как раз у Фаулера была мысль, что при первом анализе чужой реализации надо смотреть на интенсивность взаимодействия отдельных подсистем.
Претензия к автору кода должна быть не
- Почему ты меняешь работу с Random, не прочитав доки по Random? Ты что, не знаешь, как работает Random?
а более адекватная и универсальная
- Ты же видишь, что Random это что-то внешнее, почему не изучил его работу?
О каком влиянии на внешнее можно говорить?
1) этот же random может вызываться и в других строках
2) индексатор у notations - это метод и в зависимости от реализации может вносить изменения
Из Main Random выйдет корректным. А внешний код не имеет права делать никаких предположений о том, как вызывался Random в Main. Тоже самое относится и к notations. Есть контракт Notations? Он соблюдён? Какие вопросы?!
А вот если Notations требует, чтобы его дважды вызывали (квадратные скобки могут быть вызваны только парами, например), то он и должен соответствующий контракт предоставлять.
Либо, существует доверенный контракт внутри алгоритма (тесная связь, неделимая часть, критическая область и т.п.).
Либо, вы запрограммировали алгоритм с ошибкой.
Либо у вас допустимо деление на ноль и ничего не изменилось.
Либо у вас неделимый кусок и вы неверно запрограммировали алгоритм.
Либо у вас существует предусловие на строчку var x = 1.0 / (n1-n2), которое формальное отсутствует, то есть ваш алгоритм неверно запрограммирован.
Из неверного можно получить ЧТО УГОДНО.
Либо потребителю всё равно, что там недельное кеширование, либо это описано в документации.
Повторяю: если человек не читает документации к коду, то может произойти ВСЁ ЧТО УГОДНО. С таким же успехом можно заменить вызов + на - и удивляться.
Вы читать умеете?
Я ясно написал, что notation предоставил контракт [], следовательно я в праве использовать его. А если, по какой-то причине, это не так, значит и контракт был бы соответствующий.
Или опять мы падаем в дыру неверно запрограммированного кода поставщика. Тогда может быть что угодно.
>Notations, если вы полагаете, что он внешний, не изменился.
Notation остался корректным. Пригодным для дальнейшего использования. Я не заменял контракт в переменной notations.
Гей-сленг? http://tinyurl.com/cnstaa9
даже после этой ссылки мой мозг не может не ассоциировать сочетание jk с матаном, тензорами и прочей ненужной херней
схемота совсем не напрягала, хоть и была серьезным предметом
Чисто мои умозаключения. Может я и не прав.
Да, но у меня тоже с JK триггером ассоциируется.
И про него даже была игра.
А большинство проблем программирования, на мой взгляд, проистекают из того, что "опопсев", программирование лишилось качественного формального представления. Если в алгоритмике дела ещё сложились, то в управлении алгоритмами беда... ООП тому наглядный пример. Недостаток формального -- одна из центральных проблем. Слишком сильно люди тянули за ниточку "ближе к реальности". Да вот беда, программа по прежнему не может оперировать императивами, ей нужна хорошая формализация. И мы проектируем по "здравому смыслу", а конструируем согласно формальному. Вроде бы как архитектор дом нарисовал весь разэдакий, а конструктор потом глядит на это дело и не понимает, как пятый этаж может висеть в воздухе...
Поясню на примере: часто звучит рекомендация разбивать на составляющие методы, занимающие больше одного экрана. Если неразумно применять эту рекомендацию при рефакторинге, может получиться намного хуже чем было, хотя формально она будет соблюдена.
В рассматриваемом случае достаточно общего понимания что делает код (выбирает два случайных элемента), чтобы оставить всё как есть.
Я не отрицаю существования пограничных случаев, где выбор того или иного варианта реализации становится практически субъективным. Но здесь и сейчас как раз всё просто.
А постусловие то было. "В n1 и n2 лежат 2 псевдослучайных числа (маловероятно, что одинаковых)". И его нарушили подобным рефакторингом.
Кроме того, "более вероятно", что n1 и n2 внутренние переменные алгоритма Main, и никто никогда не будет обращать внимание на то, как именно они получены (являются ли он псевдослучайными, например) и равны ли они друг другу.
ГПСЧ редко выдает два одинаковых числа подряд (но может, и выдает!). Именно поэтому я и пишу "маловероятно", а не "никогда". Вот тут этот маловероятный случай прекрасно отбрасывается, и код работает.
Если же нарушить инвариант "маловероятности совпадений n1 и n2", превратив его в "n1 всегда такое же, как n2", код внезапно перестанет работать.
> подчиняется формализму классической логики
С тех пор, как программа способна обмениваться данными с внешним миром, никакой формальной логике она уже не подчиняется.
Никаких вероятностей не нужно, чтобы выйти из цикла. Я выхожу с вероятностью 1.
Вот это и есть формализм классической логики. В условие вы можете получить только ложь или истину. Больше ничего. При этом, для одних и тех же входных данных вы всегда получаете одинаковый результат. В основе любой рациональности лежит логика. Какая бы рациональность не была: научная, женская, религиозная ... И какая бы ни была логика: классическая, квантовая, с неопределённостями, с противоречиями и т.д.
Но это всё не имеет отношения к делу. Это просто, чтобы вы где-нибудь в приличном обществе не брякнули, что в основе современного программирования не лежит формальной логики.
Речь не идёт о том, что алгоритм не изменится. Изменится, возможно. Речь идёт о том, что проблемы, связанные с изменением этого куска проистекают не из того, что кто-то неправильно оценил "внешние" и "внутреннее" у делегата Main, а из того, что "прежде чем что-то поколебать, его нужно изучить". Нельзя использовать что-либо, тем паче изменять, если вы не знаете, как конкретно оно работает.
Если у функции Main хотя бы есть предположительный контракт из пустоты в пустоту, то у куска кода из двух строк вообще никакого явного контракта нет! А значит там может быть что угодно! Прежде, чем рубить, нужно ознакомиться с работой всех входящих элементов да и всего алгоритма.
Единственное, что верно в твоём посте - это фраза (хоть и капитанская)
> прежде чем что-то поколебать, его нужно изучить
Но во-первых ты сам противоречишь себе. Во-вторых ты говоришь с собеседниками в спорящей манере. Именно в спорящей. Но если бы ты действительно осознавал, что
> прежде чем что-то поколебать, его нужно изучить
ты бы понял, что все комментаторы в этом треде об этом и говорят.
Более того, сам факт того, что человек запостил это здесь, говорит он это понял.
Согласен, есть. После выхода из цикла. Контракт всего цикла в целом - выдать 2 различных числа.
> В вашем коде нет "маловероятности".
Есть. Внутри цикла. ГПСЧ с небольшой но ненулевой вероятностью может выдать два одинаковых числа подряд. Чем это противоречит логике? Хорошо, я могу провести анализ конкретного ГПСЧ и написать, что в 3155 случаях из 368126387612 он выдаст одинаковые числа два раза подряд. Но зачем это делать, если можно указать, что данный факт "маловероятен, но пренебречь им нельзя"?
P.S. Тем более, что конкретную реализацию ГПСЧ я не знаю, но теория вероятности (если считать выхлоп генератора нормально распределенным), подсказывает, что вероятность невелика. Не нужно везде пихать формализмы. Во многих ситуациях достаточно здравого смысла.
То есть, кажется, что у этого куска контракт такой: без предварительных условий получить два int.
А вот в куске кода с циклом, который у вас написан, возникает некоторый дополнительный контракт, что числа не могут быть равными для корректного продолжения алгоритма.
Это, кстати, имеет отношение к вопросу о разбиении большой функции на малые. Такое разбиение требует поиска внутреннего контракта между частями алгоритма. Весьма неочевидный процесс...
В коде, который привёл bormand, числа как раз-таки должны быть равными для выхода из цикла, lol.
Вы какую-то ерунду несёте, извиняюсь. Про контракты и весьма неочевидные процессы.
Не вчитался в код bormand.
Но это не имеет отношения к делу.
ОМГ, я там написал n1 != n2... Вот так вот второпях писать код, и не тестировать его.