Видимо, тут таки конфликты в понимании слова «ошибка». Слишком уж оно эмоциональное. Но, даже если его применять, то в разработке на заказ такие «ошибки» будут даже не неустранимой составляющей работы, а просто константой обстановки (отсюда и все веяния в сторону agile). Если заказчик — внутренний, влиять обычно легче, но полного избавления от таких ошибок я не предполагаю.
> на случай атомной войны планировалась автономность до года
Р-радикально. :) Впрочем, тогда и не такие взлёты мысли были. И устройство было упрощено до предела. Не думаю, что кто-то из современных конструкторов сейчас возьмётся повторять этот подвиг в варианте с хоть каким-то расчётом на более современные средства, а не уровня древней Спарты.
> Ну тоже примерно так. Ну может 5-7, а не 3, но примерно так…
Ook.
> Во втором варианте проще вставить дополнительные операции между вызовом процедуры и использованием её результата.
Да. Но это сейчас такая вещь, которую всякие IDE должны вообще на автомате делать по указанию программиста о выделении куска выражения (и многие и делают), как и обратно. Строить на этом теорию, мне кажется, уже давно не имеет смысла.
> По ссылке все-таки, не по указателю. Указателей на данные там вообще не было.
Это я переупростил для ясности. С точки зрения C++-like терминологии это таки ссылка, даже если внутри чистейший указатель.
Тритовые — тем, что будут умножать и делить на 2, а не на 3.
А ещё есть вопрос операций типа count leading (trailing) zeros (sign zeros, etc.). Аналог сохранится, но кроме него надо будет ещё другие варианты продумывать.
Для этого нужен следующий шаг — увеличение количества миллибит в бите. Увеличение всего на 2.4% (1000 -> 1024) позволит повысить плотность упаковки картинки на 4-8%. Скорость на каналах, понятно, повысится во столько же раз.
Так Вы тогда и спецификацию Си прочитайте. В C11 (final draft) — пункт 6.2.6.2. Достаточно объёмная цитата, форматирование я уложил в плоское:
=== cut here ===
For unsigned integer types other than unsigned char, the bits of the object
representation shall be divided into two groups: value bits and padding bits (there need not be any of the latter). If there are N value bits, each bit shall represent a different power of 2 between 1 and 2, so that objects of that type shall be capable of representing values from 0 to 2**N − 1 using a pure binary representation; this shall be known as the value representation. The values of any padding bits are unspecified.
For signed integer types, the bits of the object representation shall be divided into three groups: value bits, padding bits, and the sign bit. There need not be any padding bits; signed char shall not have any padding bits. There shall be exactly one sign bit. Each bit that is a value bit shall have the same value as the same bit in the object representation of the corresponding unsigned type (if there are M value bits in the signed
type and N in the unsigned type, then M ≤ N ). If the sign bit is zero, it shall not affect the resulting value. If the sign bit is one, the value shall be modified in one of the following ways:
— the corresponding value with sign bit 0 is negated (sign and magnitude);
— the sign bit has the value −(2**M ) (two’s complement);
— the sign bit has the value −(2**(M − 1)) (ones’ complement).
Which of these applies is implementation-defined, as is whether the value with sign bit 1 and all value bits zero (for the first two), or with sign bit and all value bits 1 (for ones’ complement), is a trap representation or a normal value. In the case of sign and magnitude and ones’ complement, if this representation is a normal value it is called a negative zero.
=== end cut ===
То есть свобода по сравнению с Java, да, есть — нежёсткие размеры, возможность signed быть короче соответствующих им unsigned, и выбор метода представления отрицательных чисел не только дополнительным кодом. Но двоичность — в полный рост, слово bit(s) во всех определениях, и никакой троичной альтернативы нет.
> Понятно что можно запустить виртуальную машину на чём угодно, но вот скорость у этого будет…
И то же самое для Си. Чтобы получить язык, удобно переносимый на троичную логику, надо что-то ближе к Ada, где основные рабочие типы задаются диапазонами. И особенно надо тщательно продумать, что будет с некоторыми операциями вроде битовых сдвигов, count_leading_zeros…
А отдельной подсистемы DOS — нету, она считается «Win16 console».
Ну, стандартные источники таки разделяют их, но не буду тут спорить только из-за терминологии.
в консольной DOS-программе под Windows NT можно использовать то, что было в WIn16, но отсутствовало в DOS. Например — обращаться к сетевым файлам.
Ну там очень много чего можно было использовать через спец. интерфейсы. Например, то, что запускалось через DOS4G[W] и тому подобные экстендеры, под Win95 запускалось нативно (а даже если программа просила экстендер, тот просто "встраивал" свои действия в Windows). Для сети Win95 эмулировала SMB интерфейсы стиля Lantastic и аналогов. Но если это не выглядело Win бинарником, а был просто досовским .exe — то прямой путь к Windows-интерфейсам был недоступен (можно было требовать её dllʼки, но там требовалась особая осторожность).
Вообще, этот слой там чуть ли не высшее произведение инженерной осторожности за всю историю осестроения — заслуживает отдельного рассказа (увы, я знаю оттуда дай бог чтобы 2%, и не возьмусь).
Давайте не путать изменения ТЗ с дополнениями, которые потребовали рефакторинг из-за непродуманности структуры.
Почему не путать? Как раз я не вижу причины вводить тут вообще какую-то принципиальную разницу. Формально дополнение очень часто вызывает необходимость перестройки, а изменение столь же часто вызывает всего лишь поверхностную переделку отдельных компонентов. В любом случае это изменение ТЗ, а какое оно даст эффекты — непредсказуемо. Иллюстрация в тему.
100% не предусмотришь, но 95% — вполне.
В 95% мы вполне вкладывались. Оставшихся 5% хватало, чтобы последствия обсуждать ещё много лет. :) И Туполеву наверняка не ставили задачи в виде "самолёт должен летать год без посадки".
И я об этом же. Если система к движению в какую-то сторону не готова — это ошибка аналитика. Или команда программистов вообще не видит дальше спринта (а надо смотреть на 5-10 лет вперед).
Реально получалось видеть с достаточным качеством на год, в общих чертах — на три.
double V = GetV());
printf("V=%.1f\n",V);
Но второй вариант проще и в отладке и в модификации.
Ну, опустим, что они неравнозначны (вот в варианте
printf("V=%.1f\n", (double) GetV())
есть действительно полное соответствие). Если отладка это распечатать V и/или не спутать пошаговый проход GetV() с printf() — да, согласен.
Но с модификацией связи не вижу. Наоборот, первый кажется проще для модификации — за счёт отсутствия лишних сущностей. Ту же переменную V надо проследить, чтобы её значение нигде дальше не использовалось. Вот если бы был оператор типа unvar (del в Python), чтобы поставить после printf и после этого чтобы V была неизвестна — тогда не надо было бы смотреть вниз.
Указателей в алголе-60 и фортране-IV вроде не было (или не было в тех реализациях, с которыми я работал).
В Фортране IV всё передавалось по указателю. Передача по значению появилась позже. От этого возникал ряд неприятных эффектов. Но я понял идею этого пункта, спасибо.
МДА. Ну или у вас аналитики действуют методом тыка, или вы путаете изменения ТЗ с дополнениями, из у вас какое-то "настоящее" программирование типа поддержи сайта.
"У нас" было "совершенно настоящее" программирование, например, биллинговой системы плюс софтсвича, или системы мониторинга реального времени с субсекундными реакциями.
Да, значительная часть хотелок превращалась в дополнения, но были и такие, которые требовали рефакторинга с самого нижнего слоя.
Наши проекты всегда связаны с реальным миром. Мы знаем, что атомный ледокол не полетит над Москвой (даже низенько-низенько), что газонокосилка не будет печь блины, а стан для оцинковки стали не станет вязать веники.
"У нас" точно так же стойка наблюдаемых железяк не начинала улетать в космос, и даже переместиться в соседний ряд не могла. И печь блины не начинала. Но когда оказывалось, что сокращение предельного времени реакции на событие X означало, что вся старая логика детекта этого события на основании характерных свойств последовательности значений датчиков не работает, и надо менять алгоритм детекта или вводить новые датчики — в некоторых местах уровень проблем от изменения был более чем заметным.
Никакая "реальность" задачи, в Ваших терминах, не защитит от таких проблем.
Точно так же я понимаю, что на компе может не быть часов, а в байте неожиданно может оказать 32 бита,
У нас без часов там не бывало, и 32 бита на системе наблюдения — тоже, хотя для этого не нужно гоняться за изделиями загадочной российской военщины — простой Cray тоже отлично подойдёт на это. Некоторым приближением к таким диверсиям были вычислительные модули на Cell.
Так что если я решил, что какого-то изменения не будет, а оно произошло — это моя ошибка.
Вот тут принципиально расходимся. Не ошибка. Ошибка — это когда на такое изменение не успеешь отреагировать. А когда оно просто непредсказуемо, но ты сохраняешь способность реагировать на новости — это как раз нормальное рабочее состояние.
В качестве мини-примера: одно из таких направлений, очень перспективное, сорвалось из-за того, что генподрядчик попал под санкции. (Это было ещё в 11-м году, так что с нынешней политикой прямо не связано.) В результате были запущены другие направления развития. Несмотря на материальность сферы, предсказать такое невозможно. Можно только быть готовым держать систему наготове к движению в любую разумную сторону.
И да, мы могли предсказать, что направление A потребует такого-то изменения, B — другого. Но пока нет никаких достоверных данных о движении в эту сторону — браться менять смысла нет. А изменения между собой слабо совместимы, скорее конфликтуют. Так зачем спешить вводить одно, даже если видишь, куда и как оно могло бы двинуться? Чем проще и прямее реализация на каждом этапе под его требования и под гарантированную (а не предполагаемую) перспективу, тем лучше.
Чтобы было понятней — вспомните дискуссию про goto сороколетней давности. Код с goto -очень гибкий. Но и некрасивый.
Я скорее отношусь к тем, кто "GOTO considered harmful" considered harmful. Потому что и return из середины, и break/continue это смягчённое goto, и автогенерация кода может их рожать пачками, и в машинном коде оно, а не if/while, и ваще. Сам иногда применяю в типичных шаблонах (например, на голом C — объединить код cleanup-веток некоторой функции). У меня критерий к нему — чтобы код был понятен тем, кто не заражён религиозной неприязнью.
И вот это
Код с goto -очень гибкий. Но и некрасивый.
неадекватно потому, что важно не то, что "некрасивый", а потому, что бесконтрольное использование GOTO приобрело ужасающие формы совершенно без причины, и никак не на пользу производительности или другим объективным показателям.
Делая код эффективным — мы теряем в его универсальности. Делая код красивым — опять теряем в универсальности.
Второе совсем сомнительно. Первое, как правило, верно (оптимизация под конкретные частные случаи применения, если не вообще под компилятор и рантайм), но при этом ничто не мешает вернуться к универсальной версии, когда потребуется.
В моей юности процедуры на 5 страниц считались отличным (и понятным кодом). Именно в этом стиле и писали в журналах и книгах по программированию. Ну и блок глобальных данных — был вообще единственным способом эффективной связи по данным.
Не знаю, как это соотносится с моей юностью, но начинал я на Fortran. Common-блоки использовались скорее для удобства не-передачи контекста каждый раз и для замены не существовавших тогда структур, чем для собственно эффективности.
Процедуры на 5 страниц и более там и сейчас норма (на днях копался в BLAS), но в специфическом контексте, где это почти не мешает. В системном программировании такие или там, где ну очень тяжело разрезать иначе (как tcp_input() в классическом BSD), или в очень специфическом стиле (sendmail).
А что было неэффективным в случае иной связи? Слишком много возни с указателями?
RTFM, NTVDM — это основной компонент подсистемы WoW16:
Это никак не следует ни из процитированного Вами текста, ни из просто определения win-on-win. Скорее надо говорить, что NTVDM — нижележащее средство для WoW16.
Почитайте "Inside Windows 95" или Unofficail windows 95 — поймете, что только титаническим трудом они смогли заставить Win95 работать настолько стабильно.
Читал, и именно об этом и говорю. И там как раз написано, почему так — не потому, что просто вдруг оказался там кривой код (с их ресурсами они всё это исправили бы), а потому, что само построение ОС не давало шансов сделать беспроблемное устройство.
А линейка Win 3.1 загнулась после крайне неудачной WinMe:
Неужели непонятно, что красота и эффективность идет за счет специализации кода (по условиям ТЗ)?
EPARSE, простите. Красота и эффективность — следствие специализации кода, или они страдают (ухудшаются) из-за специализации кода?
Что вся декомпозиция — хороша лишь, пока программист верно понимает ТЗ и спектр его изменений?
Нет, непонятно. На практике можно считать, например, что через год изменятся 10% требований, а за десятилетний цикл развития — чуть менее, чем все. (Реальные цифры с одной из моих прошлых работ.) Но каким образом из этого следует рекомендация писать всё так, что не заботиться о его сопровождении? Ведь даже если 20% изменилось, остальные 80% те же, а сопровождать надо каждый день.
А если программер построил "мост вдоль реки", то его разворот обойдется дороже, чем написать его заново.
Если построен мост вдоль реки по предыдущему ТЗ, то, значит, так и надо было. Но если продолжать использовать эту аналогию, то очень вероятно, что те же решения (быки-опоры, пролёты, методы их сцепления, покрытие для дороги) годятся для моста что вдоль, что поперёк, что через реку, что через каменный провал. И мне такая интерпретация кажется более реальной.
И вот вам пример, чем быдлокод лучше. Известная "Задача о восьми ферзях": Простой вариант с 8 циклами — легко обеспечивает переход к доскам непрямоугольной формы. А вот быстрый алгоритм Дейкстры…
Ну я её вообще писал через бэктрекинг с переходами. Но если и брать какой-то вывод из этого примера, то такой, что предсказать изменение задач в большинстве случаев невозможно. Пусть в какой-то момент доска превращается в кубическую гранецентрированную кристаллическую решётку — и оба метода перестают быть применимыми, от слова "совсем". У меня были аналоги такой ситуации, и это не примхи маркетинга, а осмысленные бизнес-требования.
Давайте разделим:
Быдлокод — это простой, некрасивый код, написанный в лоб.
Вот из написания "в лоб" никак не следуют огромные процедуры и связь через глобальные переменные, и наоборот.
Нет, не путаю. Я явно указал, что тут два разных этапа избавления от этого наследия.
Одно дело — подсистема WoW
Про WoW я ничего не говорил. Говорил про то, что в линии NT называется NTVDM, а в 9x как-то иначе. Сейчас уточнил — да, оно в 32-битных версиях вроде бы есть и сейчас.
Но сказалась усталость кода…
Или скорее то, что альтернативный перспективный код был давно стабилизирован и готов к использованию.
На современной элементной базе полноценный barrel shifter дешевле, чем раскладка сдвига на много бит в цикл по одному биту.
Хотя x86 и сейчас не гарантирует быстрое выполнение для всяких нелепостей вроде RCR на несколько бит.
И любой работающий быдлокод — в 100 раз лучше неработающей красоты.
А вы действительно не путаете проблемность целевой области и заточку кода под неё (что может включать в себя массу адских хаков на частные случаи исключительно из-за ТЗ) и некачественность самого кода?
Если первое, то это не принято называть быдлокодом (разве что быдлозадачей).
Если второе, то покэпствую
1) красивый неработающий код, скорее всего, легче довести до рабочего состояния;
2) после этого он лучше сопровождаем, в отличие от быдлокода.
Пример с Doom и куском для NeXT, кстати, тут очень хорош дидактически :) С одной стороны, там очевидные странности в виде магических констант, которые по обычным нормативам надо описать в виде #define. Но я бы тут вместо этого поставил комментарий с описанием смысла конкретного числа.
С другой стороны, стиль, рекомендуемый во многих местах, потребовал бы сделать тут безусловно вызванное макро, которое было бы определено в непустое действие только для NeXT. А вот это уже хуже потерей локальности — надо идти неизвестно куда только для того, чтобы узнать, что для 99.999% случаев макро просто пустое.
Но верно и то, что линейка Win95 загнулась, потому что просто не смогла развиваться.
Связано ли это с качеством её кода? Или всё-таки с тем, что принципиально беззащитный дизайн перестал котироваться, а компы дотянули до мощности, когда NT-based решения перестали быть аццким тормозом?
Насколько я в курсе, там существенные затраты шли таки на проблемы совместимости с DOS. Избавление от неё сначала при переходе на Win2000, а затем (в Vista) при устранении DOS mode и 16-битки — были громкими праздниками.
Кстати вы представляете себе, что такое переделать действующий реактор
Представляю, примерно. Насколько может представлять это человек технического образования другой специальности. Конечно, это огромные затраты и объём работ. Но последствия у только одной аварии — больше.
Но, если учесть, что те же стержни вообще планово менялись, то эта работа и так должна была быть сделана. Тут больше административные и документальные проблемы.
если машину на скользком участке заносит от неудачного маневра, то виновата конструкция?
Если у неё есть компонент, который при начале заноса работает на его усиление — да, виновата конструкция. Это хороший аналог той диверсии в конструкции стержней.
Кстати, Смоленская АЭС с реактором РБМК, как на Чернобыле, в 2011 году получила высокую оценку экспертами МАГАТЭ
После Чернобыльской аварии все РБМК подверглись коренной переработке управляющих конструкций и пересмотру правил эксплуатации.
Это очень удобно — называть всех на «вы», даже свою кошку.
И неудобно тем, что нет отличия между единственным и множественным числом. Всё-таки это различие в грамматике придумали не зря.
Есть языки, в которых даже в самом уважительном случае норма — "ты" (например, иврит). Есть такие, где отдельная пара ты/вы подчёркнуто уважительного вида (классический испанский с uste, usted, хотя регионально там и другие формы). Мне всё это кажется более полезным, чем просто выкидывание одной формы.
У меня претензия к именованию участников. Обычно в криптографии Алиса и Боб — две стороны защищённого взаимодействия, тут скорее Алиса держала бы сервер, выдающий токены, а Боб — законный пользователь. А воры токенов — это в первую очередь Крейг (Craig). Вот вроде полный список.
Результат — читая статью, на каждом абзаце приходится переименовывать в голове.
Данную статью уже не исправить из-за комментариев, где повторены эти имена, но на будущее прошу не сбивать в таких основах.
Кэши собственно данных, типа L0, в этом не участвуют, читать-писать основное содержимое страниц не нужно. А вот создать копию VM map процесса — задача достаточно затратная, включая карты physical maps с инкрементом счётчиков использования (вот тут наверняка кэш и насилуется).
Видимо, тут таки конфликты в понимании слова «ошибка». Слишком уж оно эмоциональное. Но, даже если его применять, то в разработке на заказ такие «ошибки» будут даже не неустранимой составляющей работы, а просто константой обстановки (отсюда и все веяния в сторону agile). Если заказчик — внутренний, влиять обычно легче, но полного избавления от таких ошибок я не предполагаю.
> на случай атомной войны планировалась автономность до года
Р-радикально. :) Впрочем, тогда и не такие взлёты мысли были. И устройство было упрощено до предела. Не думаю, что кто-то из современных конструкторов сейчас возьмётся повторять этот подвиг в варианте с хоть каким-то расчётом на более современные средства, а не уровня древней Спарты.
> Ну тоже примерно так. Ну может 5-7, а не 3, но примерно так…
Ook.
> Во втором варианте проще вставить дополнительные операции между вызовом процедуры и использованием её результата.
Да. Но это сейчас такая вещь, которую всякие IDE должны вообще на автомате делать по указанию программиста о выделении куска выражения (и многие и делают), как и обратно. Строить на этом теорию, мне кажется, уже давно не имеет смысла.
> По ссылке все-таки, не по указателю. Указателей на данные там вообще не было.
Это я переупростил для ясности. С точки зрения C++-like терминологии это таки ссылка, даже если внутри чистейший указатель.
А ещё есть вопрос операций типа count leading (trailing) zeros (sign zeros, etc.). Аналог сохранится, но кроме него надо будет ещё другие варианты продумывать.
=== cut here ===
For unsigned integer types other than unsigned char, the bits of the object
representation shall be divided into two groups: value bits and padding bits (there need not be any of the latter). If there are N value bits, each bit shall represent a different power of 2 between 1 and 2, so that objects of that type shall be capable of representing values from 0 to 2**N − 1 using a pure binary representation; this shall be known as the value representation. The values of any padding bits are unspecified.
For signed integer types, the bits of the object representation shall be divided into three groups: value bits, padding bits, and the sign bit. There need not be any padding bits; signed char shall not have any padding bits. There shall be exactly one sign bit. Each bit that is a value bit shall have the same value as the same bit in the object representation of the corresponding unsigned type (if there are M value bits in the signed
type and N in the unsigned type, then M ≤ N ). If the sign bit is zero, it shall not affect the resulting value. If the sign bit is one, the value shall be modified in one of the following ways:
— the corresponding value with sign bit 0 is negated (sign and magnitude);
— the sign bit has the value −(2**M ) (two’s complement);
— the sign bit has the value −(2**(M − 1)) (ones’ complement).
Which of these applies is implementation-defined, as is whether the value with sign bit 1 and all value bits zero (for the first two), or with sign bit and all value bits 1 (for ones’ complement), is a trap representation or a normal value. In the case of sign and magnitude and ones’ complement, if this representation is a normal value it is called a negative zero.
=== end cut ===
То есть свобода по сравнению с Java, да, есть — нежёсткие размеры, возможность signed быть короче соответствующих им unsigned, и выбор метода представления отрицательных чисел не только дополнительным кодом. Но двоичность — в полный рост, слово bit(s) во всех определениях, и никакой троичной альтернативы нет.
> Понятно что можно запустить виртуальную машину на чём угодно, но вот скорость у этого будет…
И то же самое для Си. Чтобы получить язык, удобно переносимый на троичную логику, надо что-то ближе к Ada, где основные рабочие типы задаются диапазонами. И особенно надо тщательно продумать, что будет с некоторыми операциями вроде битовых сдвигов, count_leading_zeros…
Ну, стандартные источники таки разделяют их, но не буду тут спорить только из-за терминологии.
Ну там очень много чего можно было использовать через спец. интерфейсы. Например, то, что запускалось через DOS4G[W] и тому подобные экстендеры, под Win95 запускалось нативно (а даже если программа просила экстендер, тот просто "встраивал" свои действия в Windows). Для сети Win95 эмулировала SMB интерфейсы стиля Lantastic и аналогов. Но если это не выглядело Win бинарником, а был просто досовским .exe — то прямой путь к Windows-интерфейсам был недоступен (можно было требовать её dllʼки, но там требовалась особая осторожность).
Вообще, этот слой там чуть ли не высшее произведение инженерной осторожности за всю историю осестроения — заслуживает отдельного рассказа (увы, я знаю оттуда дай бог чтобы 2%, и не возьмусь).
Почему не путать? Как раз я не вижу причины вводить тут вообще какую-то принципиальную разницу. Формально дополнение очень часто вызывает необходимость перестройки, а изменение столь же часто вызывает всего лишь поверхностную переделку отдельных компонентов. В любом случае это изменение ТЗ, а какое оно даст эффекты — непредсказуемо. Иллюстрация в тему.
В 95% мы вполне вкладывались. Оставшихся 5% хватало, чтобы последствия обсуждать ещё много лет. :) И Туполеву наверняка не ставили задачи в виде "самолёт должен летать год без посадки".
Реально получалось видеть с достаточным качеством на год, в общих чертах — на три.
Ну, опустим, что они неравнозначны (вот в варианте
есть действительно полное соответствие). Если отладка это распечатать V и/или не спутать пошаговый проход GetV() с printf() — да, согласен.Но с модификацией связи не вижу. Наоборот, первый кажется проще для модификации — за счёт отсутствия лишних сущностей. Ту же переменную V надо проследить, чтобы её значение нигде дальше не использовалось. Вот если бы был оператор типа unvar (del в Python), чтобы поставить после printf и после этого чтобы V была неизвестна — тогда не надо было бы смотреть вниз.
В Фортране IV всё передавалось по указателю. Передача по значению появилась позже. От этого возникал ряд неприятных эффектов. Но я понял идею этого пункта, спасибо.
"У нас" было "совершенно настоящее" программирование, например, биллинговой системы плюс софтсвича, или системы мониторинга реального времени с субсекундными реакциями.
Да, значительная часть хотелок превращалась в дополнения, но были и такие, которые требовали рефакторинга с самого нижнего слоя.
"У нас" точно так же стойка наблюдаемых железяк не начинала улетать в космос, и даже переместиться в соседний ряд не могла. И печь блины не начинала. Но когда оказывалось, что сокращение предельного времени реакции на событие X означало, что вся старая логика детекта этого события на основании характерных свойств последовательности значений датчиков не работает, и надо менять алгоритм детекта или вводить новые датчики — в некоторых местах уровень проблем от изменения был более чем заметным.
Никакая "реальность" задачи, в Ваших терминах, не защитит от таких проблем.
У нас без часов там не бывало, и 32 бита на системе наблюдения — тоже, хотя для этого не нужно гоняться за изделиями загадочной российской военщины — простой Cray тоже отлично подойдёт на это. Некоторым приближением к таким диверсиям были вычислительные модули на Cell.
Вот тут принципиально расходимся. Не ошибка. Ошибка — это когда на такое изменение не успеешь отреагировать. А когда оно просто непредсказуемо, но ты сохраняешь способность реагировать на новости — это как раз нормальное рабочее состояние.
В качестве мини-примера: одно из таких направлений, очень перспективное, сорвалось из-за того, что генподрядчик попал под санкции. (Это было ещё в 11-м году, так что с нынешней политикой прямо не связано.) В результате были запущены другие направления развития. Несмотря на материальность сферы, предсказать такое невозможно. Можно только быть готовым держать систему наготове к движению в любую разумную сторону.
И да, мы могли предсказать, что направление A потребует такого-то изменения, B — другого. Но пока нет никаких достоверных данных о движении в эту сторону — браться менять смысла нет. А изменения между собой слабо совместимы, скорее конфликтуют. Так зачем спешить вводить одно, даже если видишь, куда и как оно могло бы двинуться? Чем проще и прямее реализация на каждом этапе под его требования и под гарантированную (а не предполагаемую) перспективу, тем лучше.
Я скорее отношусь к тем, кто "GOTO considered harmful" considered harmful. Потому что и return из середины, и break/continue это смягчённое goto, и автогенерация кода может их рожать пачками, и в машинном коде оно, а не if/while, и ваще. Сам иногда применяю в типичных шаблонах (например, на голом C — объединить код cleanup-веток некоторой функции). У меня критерий к нему — чтобы код был понятен тем, кто не заражён религиозной неприязнью.
И вот это
неадекватно потому, что важно не то, что "некрасивый", а потому, что бесконтрольное использование GOTO приобрело ужасающие формы совершенно без причины, и никак не на пользу производительности или другим объективным показателям.
Второе совсем сомнительно. Первое, как правило, верно (оптимизация под конкретные частные случаи применения, если не вообще под компилятор и рантайм), но при этом ничто не мешает вернуться к универсальной версии, когда потребуется.
Не знаю, как это соотносится с моей юностью, но начинал я на Fortran. Common-блоки использовались скорее для удобства не-передачи контекста каждый раз и для замены не существовавших тогда структур, чем для собственно эффективности.
Процедуры на 5 страниц и более там и сейчас норма (на днях копался в BLAS), но в специфическом контексте, где это почти не мешает. В системном программировании такие или там, где ну очень тяжело разрезать иначе (как tcp_input() в классическом BSD), или в очень специфическом стиле (sendmail).
А что было неэффективным в случае иной связи? Слишком много возни с указателями?
Это никак не следует ни из процитированного Вами текста, ни из просто определения win-on-win. Скорее надо говорить, что NTVDM — нижележащее средство для WoW16.
Читал, и именно об этом и говорю. И там как раз написано, почему так — не потому, что просто вдруг оказался там кривой код (с их ресурсами они всё это исправили бы), а потому, что само построение ОС не давало шансов сделать беспроблемное устройство.
Которую мало кто ставил.
EPARSE, простите. Красота и эффективность — следствие специализации кода, или они страдают (ухудшаются) из-за специализации кода?
Нет, непонятно. На практике можно считать, например, что через год изменятся 10% требований, а за десятилетний цикл развития — чуть менее, чем все. (Реальные цифры с одной из моих прошлых работ.) Но каким образом из этого следует рекомендация писать всё так, что не заботиться о его сопровождении? Ведь даже если 20% изменилось, остальные 80% те же, а сопровождать надо каждый день.
Если построен мост вдоль реки по предыдущему ТЗ, то, значит, так и надо было. Но если продолжать использовать эту аналогию, то очень вероятно, что те же решения (быки-опоры, пролёты, методы их сцепления, покрытие для дороги) годятся для моста что вдоль, что поперёк, что через реку, что через каменный провал. И мне такая интерпретация кажется более реальной.
Ну я её вообще писал через бэктрекинг с переходами. Но если и брать какой-то вывод из этого примера, то такой, что предсказать изменение задач в большинстве случаев невозможно. Пусть в какой-то момент доска превращается в кубическую гранецентрированную кристаллическую решётку — и оба метода перестают быть применимыми, от слова "совсем". У меня были аналоги такой ситуации, и это не примхи маркетинга, а осмысленные бизнес-требования.
Вот из написания "в лоб" никак не следуют огромные процедуры и связь через глобальные переменные, и наоборот.
Нет, не путаю. Я явно указал, что тут два разных этапа избавления от этого наследия.
Про WoW я ничего не говорил. Говорил про то, что в линии NT называется NTVDM, а в 9x как-то иначе. Сейчас уточнил — да, оно в 32-битных версиях вроде бы есть и сейчас.
Или скорее то, что альтернативный перспективный код был давно стабилизирован и готов к использованию.
Я таки удивился, что Вы считаете, что я считаю иначе. Я не дал к этому никакого повода.
Спасибо, кэп. :)
На современной элементной базе полноценный barrel shifter дешевле, чем раскладка сдвига на много бит в цикл по одному биту.
Хотя x86 и сейчас не гарантирует быстрое выполнение для всяких нелепостей вроде RCR на несколько бит.
А вы действительно не путаете проблемность целевой области и заточку кода под неё (что может включать в себя массу адских хаков на частные случаи исключительно из-за ТЗ) и некачественность самого кода?
Если первое, то это не принято называть быдлокодом (разве что быдлозадачей).
Если второе, то покэпствую
1) красивый неработающий код, скорее всего, легче довести до рабочего состояния;
2) после этого он лучше сопровождаем, в отличие от быдлокода.
Пример с Doom и куском для NeXT, кстати, тут очень хорош дидактически :) С одной стороны, там очевидные странности в виде магических констант, которые по обычным нормативам надо описать в виде #define. Но я бы тут вместо этого поставил комментарий с описанием смысла конкретного числа.
С другой стороны, стиль, рекомендуемый во многих местах, потребовал бы сделать тут безусловно вызванное макро, которое было бы определено в непустое действие только для NeXT. А вот это уже хуже потерей локальности — надо идти неизвестно куда только для того, чтобы узнать, что для 99.999% случаев макро просто пустое.
Связано ли это с качеством её кода? Или всё-таки с тем, что принципиально беззащитный дизайн перестал котироваться, а компы дотянули до мощности, когда NT-based решения перестали быть аццким тормозом?
Насколько я в курсе, там существенные затраты шли таки на проблемы совместимости с DOS. Избавление от неё сначала при переходе на Win2000, а затем (в Vista) при устранении DOS mode и 16-битки — были громкими праздниками.
Именно. Перевод на "мирные рельсы" без адекватного обеспечения (хотя и начальная разработка в таком опасном виде).
Неотъемлемая компонента причины, вместе с проблемами конструкции.
Представляю, примерно. Насколько может представлять это человек технического образования другой специальности. Конечно, это огромные затраты и объём работ. Но последствия у только одной аварии — больше.
Но, если учесть, что те же стержни вообще планово менялись, то эта работа и так должна была быть сделана. Тут больше административные и документальные проблемы.
Если у неё есть компонент, который при начале заноса работает на его усиление — да, виновата конструкция. Это хороший аналог той диверсии в конструкции стержней.
После Чернобыльской аварии все РБМК подверглись коренной переработке управляющих конструкций и пересмотру правил эксплуатации.
И неудобно тем, что нет отличия между единственным и множественным числом. Всё-таки это различие в грамматике придумали не зря.
Есть языки, в которых даже в самом уважительном случае норма — "ты" (например, иврит). Есть такие, где отдельная пара ты/вы подчёркнуто уважительного вида (классический испанский с uste, usted, хотя регионально там и другие формы). Мне всё это кажется более полезным, чем просто выкидывание одной формы.
У меня претензия к именованию участников. Обычно в криптографии Алиса и Боб — две стороны защищённого взаимодействия, тут скорее Алиса держала бы сервер, выдающий токены, а Боб — законный пользователь. А воры токенов — это в первую очередь Крейг (Craig). Вот вроде полный список.
Результат — читая статью, на каждом абзаце приходится переименовывать в голове.
Данную статью уже не исправить из-за комментариев, где повторены эти имена, но на будущее прошу не сбивать в таких основах.
Кэши собственно данных, типа L0, в этом не участвуют, читать-писать основное содержимое страниц не нужно. А вот создать копию VM map процесса — задача достаточно затратная, включая карты physical maps с инкрементом счётчиков использования (вот тут наверняка кэш и насилуется).