Код, который невозможно поддерживать (часть 2)

http://mindprod.com/jgloss/unmain.html
  • Перевод
Продолжение этого топика — вторая и третья главы эссе «Unmaintainable Code». Несколько перекликается с первой, но описанные методы уже не так очевидны (а некоторые отличаются поистине дьявольской изобретательностью и не меньшей злокозненностью). Ах да, с заявленного в прологе языка Java автор незаметно переключился на C/C++.

Камуфляж



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

1. Пишите «эффективный» код

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

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

2. Комментарии, притворяющиеся кодом

Комментируйте фрагменты кода так, чтобы на первый взгляд они казались актуальными.
for ( j=0; j<array_len; j+ =5 )
   {
   total += array[j+0];
   total += array[j+1]; /* Тело цикла развернуто для ускорения работы
   total += array[j+2]; */
   total += array[j+3];
   total += array[j+4];
   }

Без подсветки кода вы бы заметили, что средняя строка закомментирована?
(Не представляю, на какую среду разработки рассчитан этот метод — даже в Far есть плагин подсветки кода. Видимо, предполагается сочетать его с неправильными расширениями файла, для которых /* */ не распознается как комментарий — прим.пер.)

3. Пространства имен

В C struct/union и typedef struct/union принадлежат к разным пространствам имен; следовательно, одно и то же имя можно (и нужно) использовать в обоих. Желательно делать их почти совместимыми.

typedef struct { char* pTr; int lEn; } snafu;

struct snafu { unsigned cNt; char* pTr; int lEn; } A;


4. Спрятанные макросы

Прячьте определения макросов в толще бессмысленных комментариев; тогда сопровождающий проскочит все комментарии разом и не обнаружит макрос. Используйте такой макрос для замены какого-нибудь легального выражения языка на что-нибудь очень странное:

#define a=b a=0-b

(Не знаю, что имел в виду автор; этот макрос в коде на C/C++ порождает ошибку, если в коде появляется переменная a, и благополучно игнорируется, если такой переменной нет. C/C++ тоже все-таки не дураки писали :-) — прим.пер.)

5. Притворитесь занятыми

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

#define fastcopy(x,y,z) /*xyz*/
:
fastcopy(array1, array2, size);


6. Переопределяйте функции

Создавайте «функции»-дубли стандартных (макросы с параметрами), которые делают что-то совсем неожиданное. (Особые маньяки могут таким образом переопределить десяток функций, которые может захотеть использовать человек, вносящий исправления. Так, например, в пару к макросу #define abs(a) (-2*a) можно написать свою громоздкую функцию вычисления модуля и использовать ее, демонически смеясь над попытками напарника заменить ее на нормальный модуль — прим.пер.)

7. Переносы в именах переменных

Помните, что препроцессор C расценивает символ \ в конце строки как перенос строки и склеивает ее со следующей? Отлично! Творчески подойдите к разбиению длинных имен переменных на строки, чтобы максимально затруднить нахождение всех обращений к этим переменным простым поиском.

8. Выбирайте зарезервированные слова для произвольных примеров

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

9. Имена в коде vs имен в интерфейсе

Проследите, чтобы имена переменных не имели ничего общего с названиями в документации и интерфейсе. Например, поле «Postal Code» можно хранить в переменной zip.

10. Скажите переименованиям «нет»

Для синхронизации двух фрагментов кода не переименовывайте переменные; лучше переопределите их при помощи #define. Создавайте побольше синонимов для одной и той же переменной в разных файлах, чтобы воспрепятствовать текстовому поиску.

11. Обходите запрет на глобальные переменные

Для этого определите статическую глобальную структуру, содержащую все переменные, которые вам понадобятся, и назовите ее EverythingYoullEverNeed. В функции передавайте эту структуру (а лучше указатель на нее под названием handle), для создания иллюзии отсутствия глобальных переменных.

12. Перегружайте операторы

Замечательное свойство перегрузки операторов позволяет создавать свои операторы +, -, /, *, совершенно не относящиеся к арифметике. В конце концов, если Страуструп использует операторы сдвига (>> и <<) для потокового ввода-вывода, чем вы хуже?

13. #define & #ifdef

Как видно из предыдущих пунктов, директивы препроцессора заслуживает отдельной оды благодарных маскировщиков; едва ли что-то другое позволяет внести столько беспорядка в код. Выражения #define замечательно маскируются под функции и переменные. Творческое применение #ifdef позволяет использовать разные версии функции в зависимости от того, в каком порядке и в каких количествах включены заголовочные файлы. Попробуйте разобраться, что делает следующий код:

#ifndef DONE
#ifdef TWICE
// put stuff here to declare 3rd time around
void g(char* str);
#define DONE
#else // TWICE
#ifdef ONCE
// put stuff here to declare 2nd time around
void g(void* str);
#define TWICE
#else // ONCE
// put stuff here to declare 1st time around
void g(std::string str);
#define ONCE
#endif // ONCE
#endif // TWICE
#endif // DONE


14. Директивы компилятора

Еще одна вещь, удобная для изменения поведения кода — ведь это то, зачем они создавались.

15. Отвлекающие маневры

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

Документация



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

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

1. Лгите

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

2. Документируйте очевидное

Приправьте код комментариями типа /* increment i */, в то же время избегайте комментирования сомнительных мест — назначения метода или смысла выполняемых действий.

3. «Что», а не «зачем»

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

4. Избегайте документирования «очевидного»

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

5. К вопросу о шаблонах документации

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

6. К вопросу о проектной документации

Допустим, вам нужно реализовать некий сложный алгоритм. Используйте классический принцип разработки ПО: первым делом создайте проект этого алгоритма. Напишите очень детальный (чем детальнее, тем лучше) документ, который бы описывал его пошагово, в виде многоуровневой (минимум 5 уровней) иерархии вложенных пунктов с автоматической нумерацией. Убедитесь, что в итоге получилось не менее 500 пунктов. Так, примером одного пункта может быть

1.2.4.6.3.13 - Display all impacts for activity where selected mitigations can apply (short pseudocode omitted).

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

7. Единицы измерения

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

8. Баги

Никогда не документируйте баги в чужом коде. Если вы подозреваете, что где-то там скрылся баг, оставьте это при себе. Если у вас есть идеи по реорганизации кода, бога ради, не записывайте их. Подумайте, что случится, если ваш комментарий увидит автор кода, руководство, клиент? Да вас ведь могут уволить! Впрочем, анонимный комментарий «Это нужно исправить» творит чудеса, особенно если неясно, к чему он относится.

9. Описание переменных

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

10. Унизительные комментарии

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

* Этот прием слишком сложен для олухов из Software Services Inc.; они, пожалуй,
* потратили бы в 50 раз больше памяти и времени с использованием тупых методов из <math.h>


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

11. Комментируйте так, будто это COBOL на перфокартах

Отказывайтесь от возможностей сред разработки, не верьте слухам о том, что определения функций и переменных всегда в одном клике от от их использования и рассчитывайте на то, что код, написанный в Visual Studio 6.0, будет сопровождаться средствами edlin или vi. Драконовские требования к комментариям — отличный способ похоронить код.

12. Комментарии в стиле Monty Python

Комментарий к методу makeSnafucated должен состоять из ровно одной строки: /* make snafucated */. Никогда и нигде не определяйте, что такое snafucated — это же любой дурак знает.

13. Устаревший код

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

Ну. И что?
Реклама
Комментарии 57
  • НЛО прилетело и опубликовало эту надпись здесь
    • –1
      Вот черт, я уже следую части этих советов :(
      • 0
        Я думаю, практически все следуют каким-то из них, хотя в большинстве своем и не нарочно. Я сама периодически нахожу свои же устаревшие комментарии и криво названные переменные (по первой части).
        • +6
          помните, маньяк уже наточил нож, и ищет ваш адрес…
          • –1
            Несправедливо( по его мнению ) уволенный админ или программист страшнее маньяка :)
            Вобще непонятно почему забыли обфускатор :) переменный с именами вида md5 выглядят намного веселее, а главное читабельнее
        • +1
          Научите на свою голову, а потом еще недоумевать будете: «где такому учат?». Шучу =) Большое спасибо Вам за перевод; первая часть хорошо так посмешила, вторую пожалуй оставлю на завтра.
          • 0
            12. Перегружайте операторы
            …В конце концов, если Страуструп использует операторы сдвига (>> и <<) для потокового ввода-вывода, чем вы хуже?


            Воистину, чем плохо? Я как-то у себя в блоге описал класс (правда, на Python-е), позволяющий делать композицию функций красиво и компактно:

            izip_fillwith0 = partial(izip_longest, fillvalue = "\x00")
            convert_string_to_byte_list = partial(imap, ord)
            xor_values = partial(reduce, operator.xor)
            
            xor_strings = compose >> \
                          (apply, izip_fillwith0) >> \
                          (imap, convert_string_to_byte_list) >> \
                          (imap, xor_values) >> \
                          (imap, chr) >> \
                          "".join
            
            ARG = ("abcdef", "ABCDEF", "5678900")
            • 0
              Для композиции функций оператор может быть понятен.
              Перегрузка, скажем, += для добавления заказа в корзину, тоже понятна.

              А вот перегрузка * для того, чтобы получить результат какой-нибудь некоммутативной операции над элементами в двух корзинах в виде строки, разделенной запятыми — это уже странно.
              • 0
                % — вполне очевидный оператор, да? Либо (наиболее популярное значение) остаток от деления, либо, в какой-нибудь бухгалтерии, «посчитать процент».
                Вспоминаем тот же самый Python: print "Day %s of %s" % (index, total)

                Я это к тому, что не так уж всё и страшно. Это всего лишь символы, другие значения у них можно и выучить.
                • +1
                  Можно и выучить. Но в статье предлагается переопределять именно основополагающие операторы, которые человек узнает еще до школы и которые очень трудно проассоциировать с какими-то другими действиями. Кроме того, эти переопределения будут действовать не во всем языке, а только в коде автора, возможно, еще и не во всем.

                  Рекордсмен с этой точки зрения, по-моему, J, в котором символы функций не имеют ничего общего с их смыслом. Ну не может нормальный человек угадать, что %: — это корень, а %~ — деление! Запомнить — может, а принять и смириться — нет :-)
                  • 0
                    Да-да, мы с вами, вроде, про J уже общались :)

                    И я не сказал бы, что там всё уж так плохо. Если помнить, что все функции идут группами по три, т.е., функции «<что-то>», «<что-то>.» и «<что-то>:» всегда как-то связаны, то… с этим вполне можно жить.
                    • 0
                      А, ну да, ну да :-) Просто J нанес мне такую глубокую моральную травму, что я до сих пор не могу оправиться, взять себя в руки и разобраться, как на нем решается квадратное уравнение, не говоря уже о том, чтобы его не вспоминать по каждому поводу :-)
                      • 0
                        Прекрасно понимаю. J, киношно выражаясь, как вино. Он ощущается лучше со временем.

                        Когда я первый раз его увидел, я немножко почитал про него, посчитал его Perl-ом в степени Perl-а, и перестал о нём думать.
                        Где-то через пару лет я (не перечитывая книг, не вращаясь в среде J-программистов, просто помня про него) неожиданно осознал, что на данный момент J (и прочие языки его семейства) — это фактически лучший способ описания параллельных вычислений.

                        Ему не хватает мелочи. Наподобие libpcre, библиотечки навроде libjlang, чтобы его можно было (аналогично тем же перловым регекспам) интегрировать в любой другой язык и писать на нём маленькие производительные вычислительные фрагменты.
                  • +2
                    % — не совсем. %s — сложно назвать оператором, это больше подстановочный символ, который мы так определили. Изначально, я не знаю математического смысла в унарном проценте.

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

                    В конце концов, country_name — тоже некоторые символы. Что мешает нам хранить в них текущую корзину клиента? :)
              • +15
                с #define TRUE (random()>0.5) ничто не сравнится.
                • НЛО прилетело и опубликовало эту надпись здесь
                  • 0
                    Смотря в какой предметной области. У меня — финансы (одна из), там вечно проблемы «в валюте или в эквиваленте», «в рублях или в копейках (той валюты, о которой идет речь)» и «проценты или доли» — хочешь не хочешь, научишься либо комментировать, либо называть однообразно.
                    • +2
                      Читал недавно статью про язык F#. Наверное, единственный язык общего назначения, в котором при его проектировании озаботились этим и ввели на уровне языка понятие «единицы измерения». Так что 10<m> + 15<m> = 25<m>, 10<m> + 15<s> выдаёт ошибку типизации, а 15<m> / 5<s> = 3<m/s>

                      А потом кто-то ещё говорит, что функциональные языки — странные, непонятные и неудобные :)
                      • 0
                        А там поддерживается какой-нибудь 1 * 1 / 1<s*s> = 1?
                        • +1
                          Блин,
                          1<kg> * 1<m> / 1<s * s> = 1<N>
                          • +1
                            Я эт, ссылку вообще-то дал…
                            Вот даже ещё более хорошую ссылку дам: msdn.microsoft.com/ru-ru/library/dd233243.aspx — цитирую красивое прямо оттуда:

                            // Выразить одну единицу измерения через другие
                            [<Measure>] type N = kg m / s 
                            
                            // Указать соотношения одной единицы измерения с однотипными ей:
                            let mlPerCubicCentimeter : float<ml/cm^3> = 1.0<ml/cm^3>
                            let mlPerLiter : float<ml/L> = 1000.0<ml/L>
                            
                            // Температуры и единицебезопасные функции перевода:
                            [<Measure>] type degC // temperature, Celsius/Centigrade
                            [<Measure>] type degF // temperature, Fahrenheit
                            
                            let convertCtoF ( temp: float<degC> ) = 9.0<degF> / 5.0<degC> * temp + 32.0<degF>
                            let convertFtoC ( temp: float<degF> ) = 5.0vdegC> / 9.0<degF> * ( temp - 32.0<degF>)
                            
                            // И можно даже наложить ограничение на единицы измерения аргументов функций,
                            // при этом не указывая их явно
                            let genericSumUnits ( x : float<'u>) (y: float<'u>) = x + y
                            • +1
                              Наличие этого монстрика в языке говорит о невозможности писать на нём удобные библиотеки. Или они (дизайнеры F#) считают, что единицы измерения необходимы во всех случаях, для которых предназначен язык?
                              • 0
                                Интересная логика. Вы ведь проясните, что вы имеете в виду?
                                • 0
                                  Единицы измерений нужны в решении далеко не всех задач. Не стоит ради domain-specific фичи усложнять синтаксис и семантику всего языка, если только он не предназначен как раз для решения задач с единицами измерений.

                                  Сложный синтаксис приводит к невозможности реализации систем метапрограммирования, а семантика — к усложнению средств анализа кода.
                                  • 0
                                    Единицы измерений нужны в решении далеко не всех задач.

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

                                    Сложный синтаксис приводит к невозможности реализации систем метапрограммирования

                                    Начиная с какого уровня сложности плавное повышение сложности синтаксиса приводит к скачкообразному изменению «возможности реализации систем метапрограммирования» на «невозможность реализации систем метапрограммирования»?
                                    И что вы имеете в виду под «системами метапрограммирования»? Особенно с учётом того, что F# сам по себе является функциональным языком, следовательно, с изначально доступными достаточно высокими уровнями абстракций.
                                    • 0
                                      Достаточно высокими на данный момент. Common Lisp, Tcl и, с сомнительным успехом, C++ держатся на плаву за счёт метапрограммирования (AST макросов, текстовых макросов и текстового препроцессора соответственно), а абстракции F# просто устареют и ничего с этим не поделаешь. Высокоуровневый язык без возможности расширения самого языка — это смешно.
                                      • 0
                                        Так всё-таки (помимо двух других вопросов) вы расскажете, что вы имеете в виду под «системами метапрограммирования», какие вы видите у них плюсы и по сравнению с чем? Common Lisp — это понятно, тамошнее понятие макросов не является, по сути, даже «метапрограммированием» по отношению к «обычному программированию» на нём же, это просто равноправное средство языка. Tcl — аналогично, это «Lisp без скобок». А вот C++… Под метапрограммированием на нём вы имеете в виду тамошние страшненькие макросы (которые спокойно повторяются под любым другим языком, будь то хоть Python, хоть F#, с помощью, например, GPP), или, допустим, темплейты, находящиеся вполне на дефолтном уровне абстракции любого нормального функционального языка?

                                        И ещё, если вдруг для вас препроцессоры — это полезная «система метапрограммирования», то как сложный синтаксис может помешать использовать тот же GPP?

                                        (Если ответите, но сами про F# не почитаете — вас ждёт интересный и приятный сюрприз).
                                        • 0
                                          В этом и сомнительность успеха C++. :) Текстовый препроцессор — отличное средство удержать язык на плаву любой ценой, если это кому-то надо. Сложный синтаксис им никак не мешает, но и пользы от GPP немного.

                                          У меня вопрос. Почему макросы CL — это средство языка? Макросы вычисляются при компиляции и выдают программу, которую компилятор преобразует в машинный код или байткод, т.е. макросы пишут готовую программу. Это ли не определение метапрограммирования? Вот в Tcl это просто средство языка.

                                          Про плюсы и по сравнению с чем уже рассказано: habrahabr.ru/blogs/arbeit/99146/#comment_3061341 Примеров куча в On Lisp Пола Грема и Let Over Lambda Дуга Хойта. Особенно советую последнюю почитать. Там немало полезного даже если Вы не пишете и не собираетесь писать на Лиспе.
                                          • 0
                                            У меня другой вопрос: а не overrated ли это метапрограммирование макросами, какого бы вида они ни были?

                                            В CL они являются вполне родным средством языка в том плане, что там нет принципиальных синтаксических различий между данными, кодом и кодогенерирующим кодом (макрами). Если мне не изменяет память, из любого из трёх уровней можно обращаться к любому из трёх уровней — ну, там, в макросе использовать определённую в основной области видимости функцию, и т.п.

                                            В C++, напротив, фактически три языка в одном: базовый функционально-объектный, шаблоны для генерирования базового функционально-объектного кода, и препроцессор для генерирования первых двух. Нижележащий уровень можно генерировать в вышележащем, но нельзя нормально использовать для модификации процесса генерации. Из-за слабости и разобщённости всех трёх «подъязыков» нормального метапрограммирования и не получается; причём, пожалуй, держится на плаву он всё-таки не из-за макросового подъязыка, а в первую очередь из-за достаточно мощного темплейтного подъязыка, с помощью которого и пытаются добиться мощи, хоть сколь либо приближающейся к CL-ным макрам.

                                            Но… А в функциональных языках? Там просто другая идея. Высокоуровневость семантики, ленивость, first-class функции и прочие радости позволяют переложить генерацию достаточно сложных конструкций на уровень компилятора — при этом сохраняя прозрачность кода, поддерживая строгую типизацию, обеспечивая его корректность. Те же самые ленивые вычисления — это не скрытая кодогенерация? Банальная композиция функций (которую, за счёт функциональной чистоты аргументов, среда может быть способна прекомпилировать и оптимизировать), не говоря уже про более сложные комбинаторные библиотеки — это не кодогенерация? Функции более высоких порядков, чем первого (вот, например, прелюбопытная статья, зачем кому-либо на практике может пригодиться функция шестого порядка) — чем это не лисповое макро, если учесть, что, опять же благодаря «чистоте» используемых функций, какие-то порядки из этой функции могут вычисляться компилятором? Чем это слабее, чем CL-ные макры?

                                            А, да, о сюрпризе. Впрочем, описанном даже в той статье по F#. В нём есть так называемые quotations, позволяющие получить доступ к синтаксическому дереву F#-овых конструкций. Ну да, вы уже представляете, какие возможности открываются. Да и примеры там шикарные: автоматическая переделка кода для запуска его на GPU.
                                            • 0
                                              В ответ на все вопросы предпоследнего абзаца вынужден ещё раз направить на Let Over Lambda. Ленивость, функции высших порядков в чистом языке, слабее CL-ных макр. Они находятся примерно на одном уровне со средствами Tcl.
                                • 0
                                  Как минимум странный вывод
                      • НЛО прилетело и опубликовало эту надпись здесь
                        • +2
                          А зачем это всё? Можно мне дураку объяснить?
                          • +2
                            Можно.
                            — от души посмеяться, представляя процесс разработки кода в соответствии с этими правилами.
                            — узнать себя, ужаснуться и сделать выводы (больше так не делать или срочно поправить уже сделанное).
                            — узнать коллегу, разгневаться и побежать его убивать.
                            — поиграться с фокусами, которые можно изобразить средствами #define, или задуматься над тем, сколько таких фокусов вы можете придумать/применить для своего языка.
                            — да мало ли что еще.
                            • 0
                              А это принесёт пользу хоть кому-нибудь помимо мифических лулзов?
                              • 0
                                Это может принести пользу разработчику. Если так маскировать свой код, подобное делал Леонардо ДаВинчи со многими своими изобретениями, то никто кроме разработчика не сможет, по крайней мере оперативно, поддерживать такую разработку. А это значит незаменимость сотрудника, повышение ЗП и прочее вытекающее.
                                • +1
                                  Это может привести к невозможности добавления новых идей без участия этого разработчика. Как думаешь, почему в Open Source просят писать код понятно? Чтобы любой достойный человек мог присоединиться к работе, не портя свою голову перед этим.

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

                                    Конечно так делать некорректно, но к сожалению так делают многие, и именно с целью быть «единоличником».
                                    Я не раз сталкивался с таким кодом, как я думаю и многие.
                                    • 0
                                      >Это может привести к невозможности добавления новых идей без участия этого разработчика
                                      Так это же просто отлично! Кто это там без меня собрался добавлять новые идеи? :)
                                  • 0
                                    «Узнать себя и сделать выводы» — однозначно, в порядке самосовершенствования (лично я уже удалила несколько здоровенных кусков закомментированного кода образца 2009 года).
                                    «Поиграться с #define» — вообще полезно изучать свой язык в деталях — как для общего развития, так и для разбирательств в чужих кодах авторов, следующих приведенным правилам.
                              • +1
                                Пункт 6 из раздела о документации — просто огонь!
                                • –4
                                  Уже надоело это петросянство
                                  • 0
                                    #define a=b a=0-b

                                    Если я правильно понимаю, автор хотел сказать, что если где-то в коде будет присваиваться значение b переменной a, по факту присвоится -b. И попробуй разберись потом, почему результат прямо противоположный.
                                    • 0
                                      Он-то хотел, это понятно, но этот макрос сам по себе не работает, и мне не удалось за полчаса исправить его так, чтобы заработал.
                                    • 0
                                      9. Имена в коде vs имен в интерфейсе

                                      Небольшое замечание к примеру этого пункта:

                                      Всетаки zip и Postal Code имеют кое что общее ;)

                                      пруф тут
                                      • +1
                                        Имеют, я знаю. Идея в том, чтобы заставить человека не тупо искать «postalcode» в коде, а думать, подбирать синонимы, фантазировать — в общем, максимизировать интеллектуальную нагрузку :-)
                                        • 0
                                          А потом не удивляйся, почему тебе в магазине не дадут «эту, ну как её, слева от правого края на половину трети ширины вашей ступни, ещё очень яркого, но не слишком заметного цвета». =)
                                          • +1
                                            Вот именно поэтому я предпочитаю магазины, в которых до всего могу дотянуться сама ;-)
                                      • –1
                                        > Не представляю, на какую среду разработки рассчитан этот метод

                                        Знаю одного парня, который принципиально не пользуется подсветкой и отлично работает :)
                                        • 0
                                          Открывая статью думал, что напишут что-то интересное. Не написали.

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

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

                                          Ну и да, #define TRUE <выражение> тоже имеет право на жизнь, правда лишь в том случае, если надо просто нагадить.
                                          • 0
                                            Вообще-то пока что переведены только 3 главы из 12. Первые главы многих книг описывают известные вещи для более плавного перехода к новым. Дальше будет интереснее, про многопоточность тоже есть.
                                            • 0
                                              Почитал оригинал. Забавно в целом, дальше — больше. И да, некоторые пакости, которые банальное code review не отловит нашлись. Правда, автор до совсем тяжелых гадостей не дошел, но, в принципе, если собрать все его советы и успеть их попользовать сразу, то нужный эффект будет достигнут.
                                              • 0
                                                «Успеть» — это в смысле пока маньяк, сопровождающий ваш код, не найдет ваш адрес? :-)
                                                • 0
                                                  «За это время мы успеем добежать до канадской границы!»
                                                  Нет, по «успеть» подразумевалось время между написанием чудовища и просмотром кода вышестоящими товарищами. Вот в это время надо успеть уволиться и как раз двинуть к канадской границе =)
                                                  Иначе уволят так и так, только предварительно сделают такое, что глаза будут как у совы, натянутой на глобус =)
                                          • 0
                                            Используйте имена функций и переменных длинной от 20 символов в виде случайных последовательностей и код будет практически не читаемым. Хотя это и легко победить…
                                            • 0
                                              «Код не должен выглядеть неподдерживаемым, а только быть таким»
                                              Иначе ваши безобразия быстро пресекут :-)
                                              • 0
                                                Ну тогда только левые длинные название с уклоном в комментарии ))

                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                            Самое читаемое