Pull to refresh

Comments 42

Страшный сон разработчика. Аж передернуло.
Лучшие комментарии объявляют, что делает код, и даже после изменений кода остаются прежними;

Неправда! Лучшие комментарии — те, которые пишутся при разработке кода (например, для упрощения какого-нибудь выражения, или заметки по логике программы), и потом не удаляются, даже если написанный далее код получился с использованием совсем другого подхода.
Намного лучше использовать последний функционал языка, который позволит тебе написать две непонятных строчки кода, а не пять очевидных.
Лучше использовать древний функционал, оставленный для совместимости или каких-нибудь редких случаев. Вроде union в С++.
Тогда уж надо вкладывать умные указатели в union, и обращаться таким образом к внутренним переменным. Это гарантирует, что код никогда не переведут на более свежую версию языка, и даже ключи компиляции будут менять с осторожностью :)
Тогда достаточно работать с таблицами виртуальных функций. Подменяя в них функции для выбора поведения объектов.
union — функционал древний но не устаревший)
даже goto — древний но не устаревший.

с goto пример наизусть не помню, но где то была статья по поводу выгоды goto по сравнению с другими конструкциями

с union ом могу привести пример где он не испортит ничего и будет стабильно работать на всех платформах и под всеми компилерами.

например:

class CVariant
{
union
{
int i;
double d;
short s;
long l;
} data;

enum DataType
{
INT,
DOUBLE,
LONG,

}

DataType m_type;

public:
// Главное правильно написать конструктор
// и методы добавления/извлечения
};
Я специально избегал слова «устаревший». Главное, чтобы он был непопулярным, почти забытым и небезопасным при неаккуратном использовании. А если у него ещё синтаксис будет похожим на что-то знакомое (как у union) — то вообще здорово.
while(parrot.view1.x>target) parrot.view2.y--;  // select best bits 4:7
Я тут недавно предложил #define i (*p)
Мне сказали «спасибо, попробую».
Но переопределять ключевые слова или общеупотребительные константы это слишком грубо. Тоньше надо быть, ласковее… И в действиях должен присутствовать конструктивный смысл — даже если это будет экономия нажатий на кнопки или места на экране.
Нежнее и ласковее — это, например static i386_insn i где-нибудь на 479й строчке здоровенного файла.

И ничего — люди справляются, никто не умер…
Хорошо, что i386_insn — не простой тип, а union. Иначе могли бы забыть описать переменную i в функции — и нечаянно испортить глобальную переменную. Но да, ход мыслей авторов этого хода мне нравится.
Боюсь, что если использовать этот класс по назначению — брать из него short, когда там лежит long (потому что нужны только младшие биты), сравнивать положительные double по их long представлению (потому что на данном процессоре так быстрее), пользоваться тем, что старшие биты long не изменились, когда в него положили short — то на некоторых платформах он может начать работать слегка по-другому.
Тогда это будет ошибка в компиляторе и его исправят. Подобное использование явным образом разрешено в GCC.
  x.l=-5;
  y=x.s;

Обычно мы получим y=-5. Но на процессоре в режиме big-endian будет y=-1. С альтернативными способами представления отрицательных чисел — ещё хуже. И при этом — никаких ошибок, просто работает по-другому.
Тем не менее — это поведение, определяемое реализацией и в определённых проектах вполне может быть допустимо. Например если вы работаете только и исключительно на процессорах little-endian с «обычными» отрицательными числами. Жизненный пример: JIT-компилятор из x86 кода в ARM или наоборот. Да, она на каком-нибудь 68060 не запустится. Ну и что? Зачем вам запускать его там? Что вы там с ним будете делать?

А вот если на неопределённое поведение «наступить» — тогда совсем другое дело.
А сдвиг отрицательного числа к какому из трёх типов относится?
Вы иронизируете про запуск на устаревшем 68060, но ведь не можете знать, на каком процессоре код, который вы пишете, рискнут запустить в будущем. Срок жизни кода умеет удивлять.
Если брать short, когда в нем лежит long, то тогда надо проверять его m_type на тот тип который в нем хранится (long) и этот тип явно преобразовывать к short'у Типа так:
short CVariant::as_short()
{
    short result;
    switch(m_type)
    {
     case LONG:
        result = (short)data.l;
        break;
     case DOUBLE:
        result = (short)data.d;
        break;
     ...
    }
    return result;
}



Таким образом возлагая все эти аппаратно-зависимые штуки на компилятор.
Goto вполне себе используется и очень много, особенно при компиляции новомодных конструкций. Async / await в шарпе; F# — тысячи их. Кто-нибудь хоть раз дизассемблировал код, генерируемый F#? :) А типы там вообще называются Discriminated Union.
Goto в языке высокого уровня и branch/jump в ассемблере или байт-коде это, всё-таки, немного разные конструкции. С разной статистикой использования и влиянием на поддерживаемость использующего их кода. Фрагмент ассемблерного кода без переходов понимается несколько сложнее, чем тот же кусок с переходами, хотя выполняется эффективнее.
и пропусти несколько важных шагов – ты должен был стараться, чтобы понять код, значит остальные тоже должны попотеть.
Что-то в этой фразе не так. Ты не должен «понимать код», ведь ты его пишешь. Наверное, имелось в виду что-то другое?
Пожалуй. Корректнее было бы: «ты должен был постараться написать непонятный код, значит остальные должны потрудиться, чтобы расшифровать его»
Я понял так, что «ты должен был постраться, чтобы их [важные шаги] найти, пусть и остальные потрудятся».
Эх, ещё один пост советов «от противного» в стиле задолба.ли. Как по мне, так интереснее было бы читать что-то, более приближенное к реальности.
И, да, языки меняются и нередки ситуации, когда код, который идеально десять лет назад, по сегодняшним меркам будет тянуть на троечку, а просто нормальный код будет выглядеть говнокодом.
Имхо сей опус, перенасыщенный очевидностями и гиперболами, покрытый легким налетом пафоса и содержащий жалкие попытки сарказма, выглядит довольно нелепо.
А ведь найдутся «доброжелатели», которые последуют этим советам.

Меня прям передергивает от гнева.
Я бы расстреливал за это.

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

С вертушки по чайнику такому бы руководителю.

Ох, «доброжелатели» и «последователи зомби кода», молитесь, чтобы не встретиться со мной!)
Ох, «доброжелатели» и «последователи зомби кода», молитесь, чтобы не встретиться со мной!)

А вы молитесь, чтобы не встретиться с нашим кодом!
Во-первых, если код работает, не исправляй его.

На самом деле иногда не такой уже и плохой совет )
Два рефакторинга равны одному пожару.
Поэтому рефакторинг должен быть один. Но идти постоянно.
А еще можно прямо перед релизом, когда все экстренно фиксят баги, залить какой-нибудь особо мощный рефакторинг, включающий самую важную для релиза фичу. :-)
И все будут плакать.
Главное — делать это в пятницу вечером.
NSA тремя руками за! Поскольку при таком подходе не нужно платить за вставление «закладок» и рисковать тем, что «спалишься». Очень удобно, да. Но вам-то это зачем?
Нет, платить придётся неоднократно. Вдруг их отрефакторят? Ещё и следить придётся всё время.
Отрефакторят — новых насажают, вы их найдёте и «внесёте в список», делов-то. Одно дело когда у вас одна-две «закладки» в вылизанном и выутюженном коде, другое — когда у вас коллекция из десятков и сотен «готовых к примерению» дыр в коде, который постоянно рефакторят.

Только не нужно мне рассказывать про то, что тесты, обязательный аппровал кода ревьюером, секьюрити ревьюэры, фаззеры и статические анализаторы спасут вашу задницу. Участвовал я в одном проекте, где всё это было — а ещё там были (и есть) дыры от рефакторинга. Увы и ах, но «код, который постоянно рефакторят» ⊂ «код, в котором куча дыр».

Единственный способ выловить (и исправить) ошибки в коде — это прекратить его рефакторить. Нужно оно вам или нет — это другой ворос.

Именно поэтому я на 200% уверен что в современных OS нет никаких закладок от NSA. Зачем они там? Современные методы написания кода гарантируют наличие огромного количества дыр, так зачем же «палить контору» закладками?
А что делать? Неожиданно понадобилось ускорить программу в 4 раза — иначе она на микрокомпьютере не успевает. 2.5 раза я уже нашёл, осталось ещё 1.6. Без перетряхивания архитектуры не обойтись. «Тесты, обязательный аппровал кода ревьюером, секьюрити ревьюэры, фаззеры и статические анализаторы»? — не знаю, не слышал, так что не спасут :) Радует ещё, что в другой части проекта тоже идёт активный рефакторинг. В общем, весело.
А это уже другой вопрос. Если вам нужна надёжность и безопасность — то вы сделаете этот компонент «высеченным в камне», за несколько лет отловите все ошибки — и в таком виде и будете использовать. И никакого рефакторинга, тем более «постоянно идущего». В качестве примера можно привести гипервизор в приставках — его именно так делают.

Если же вам нужно постоянно добавлять новые фичи и вообще техзадание постоянно меняется — ну значит придётся делать рефакторинг, куда деваться. Но нужно понимать что при таком подходе от кучи ошибок и дыр в безопасности вы никуда не денетесь.

Просто нужно отдавать себе отчёт в том, что ты делаешь, вот и всё. Рефакторинг, тесты и прочее — это всего-навсего инструменты. Иногда ими нужно пользоваться, а иногда — не стоит. Всё зависит от задач.

P.S. Хотя про вариант совсем без тестов я как-то не думал. Это уж как-то слишком страшно для меня…
Да, примерно половина, если не больше, признаков во внедряемом у нас продукте имеются… и нам потом его поддерживать.
На мой вкус это вторичная статья к гайдлайну “How To Write Unmaintainable Code”
https://thc.org/root/phun/unmaintain.html

>I am passing on these tips from the masters on how to write code that is so difficult to maintain, that the people who come after you will take years to make even the simplest changes. Further, if you follow all these rules religiously, you will even guarantee yourself a lifetime of employment, since no one but you has a hope in hell of maintaining the code.

Этому гайдлайну до сих пор многие следуют, создавая так массу рабочих мест.
С этим надо бороться
Ну как перевести это «that will enable you… to write legacy code immediately»? Красота же! А в перевод не попало :(
Sign up to leave a comment.

Articles