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

Основные принципы


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

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

Особые методы


1. Лгите в комментариях. Необязательно врать на каждом шагу: достаточно того, что комментарии никак не будут связаны с кодом.

2. Заполняйте код комментариями вроде /* прибавить 1 к i */, но никогда не указывайте в коде такие общие вещи, как назначение модуля или метода.

3. Убедитесь в том, что каждый метод делает чуть больше (или чуть меньше), чем предполагается в его названии. Например, метод isValid(x) может, помимо прочего, переводить x в двоичную систему и сохранять результаты в базе данных.

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

5. Для создания еще большего эффекта старайтесь не пользоваться инкапсуляцией. Тем, кто вызывает тот или иной метод, необходимы все возможные подсказки, которые напомнят им, как работает этот метод.

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

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

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

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

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

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

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

Подумайте над различными вариантами написания названий, которые могут запутать других. Например, можно одновременно использовать британский colour, американский color и специфичные варианты этого слова вроде kulerz.

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

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

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

После этого вы можете случайно выравнивать код так, чтобы возникала оптическая иллюзия того, что тела циклов и условий выглядят длиннее или короче, чем должны быть, или ключевое слово else соответствуют не тому ключевому слову if.

12. Никогда не вставляйте фигурные скобки { } в своих блоках if-else, если этого не требует синтаксис. Когда в вашем коде несколько выражений и блоков if-else идут подряд, причем еще и с неправильным выравниванием, то вы можете запутать даже опытного коллегу.

13. Строго следуйте указаниям, предусматривающим отсутствие оператора goto, досрочного выхода из цикла и его прерываний, особенно, когда вы можете увеличить глубину цикла if-else как минимум еще на пять уровней.

14. Используйте длинные названия переменных, отличающихся друг от друга всего лишь одним символом или регистром. Идеальная пара переменных – swimmer и swimner.

Используйте все возможные недостатки шрифтов, не позволяющих различать ilI1| или oO08, например, в случаях с parselnt и parseInt или D0Calc и DOCalc. В данной ситуации самый подходящий символ в названии переменной – это буква l, так как с первого раза ее не отличишь от константы 1.

Имена переменных также могут отличаться только регистром, например, HashTable и Hashtable.

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

Совсем жестоко будет, если вы немного измените переменную: в начале очень длинного метода вы можете присвоить переменной одно значение, а затем где-то в середине незаметно сменить его на другое – скажем, поменять начало отсчета индексной переменной с 0 на 1. Только убедитесь, что это изменение не фиксируется в документации.

16. Пользуйтесь строчной буквой l при обозначении констант типа long. Например, 10l гораздо легче спутать с 101, чем с 10L.

17. Игнорируйте общепринятые соглашения Java об именовании классов и переменных, согласно которым, например, классы обычно пишутся с заглавной буквы, переменные – со строчной, константы – полностью заглавными, слова внутри названия класса/переменной пишутся с заглавной буквы. Даже компания Sun не следует этим соглашениям (примеры – instanceof/isInstanceOf, Hashtable/HashTable). Не беспокойтесь, компилятор даже не выдаст вам предупреждения.

Если все же ваше начальство заставляет вас следовать общепринятым соглашениям, каждый раз, когда у вас появляется выбор – стоит ли начинать с заглавной буквы или нет – пишите все прописными или пишите наугад, например, вы можете одновременно использовать inputFileName и outputfilename.

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

18. Никогда не используйте i как внутреннюю переменную в цикле. Можете выбрать любое название, но только не это. Вы можете специально использовать переменную i для других целей. Аналогично можно использовать n в качестве счетчика цикла.

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

Вы избавите себя от лишней работы в дальнейшем, когда в других методах нужно будет объявить те же переменные. Разработчики C++ иногда идут еще дальше и объявляют все возможные переменные глобальными.

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

Что если программист, работающий с этим кодом, увидит ваши комментарии? Что, если их увидит глава вашей компании или клиент? Вас же могут уволить.

21. Веселья ради можете подобрать как можно больше слов, обозначающих одно и то же действие, например, display, show, present. Неявно намекните, что между элементами программы якобы имеется небольшое различие, которого на самом деле нет.

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

22. В названиях функций старайтесь использовать больше абстрактных понятий, таких как it, everything, data, handle, stuff, do, routine, perform, и цифр, например, routineX48, PerformDataFunction, DoIt, HandleStuff и do_args_method.

23. В Java все параметры базового типа фактически доступны только для чтения, потому что они передаются по значению. Вызываемая процедура может изменить эти параметры, но не окажет никакого влияния на значения переменных в вызывающей процедуре. Все объекты, напротив, можно изменять, так как в данном случае по значению передается ссылка на эти объекты, то есть сам объект передается по ссылке. Поэтому вызываемая процедура как угодно может менять поля в вашем объекте.

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

24. Никогда не указывайте в комментариях единицы измерения любого типа переменных – входных, выходных или параметров, будь то футы, метры или ящики. Это имеет большое значение не столько для точности расчетов, сколько для процесса разработки в целом.

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

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

25. Инженерные расчеты можно запрограммировать двумя способами. Первый способ: перевести все входные значения в систему СИ, выполнить расчет и затем перевести выходные значения в соответствующие единицы измерения. Второй способ: проводить вычисления в различных смешанных системах измерения. Всегда выбирайте второй способ.



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

Вы можете значительно упростить свою программу, если оставите во всем приложении (в методе main) единственный оператор try-catch, который вызывает метод System.exit().

27. Компиляторы языка C преобразуют выражение myArray[i] в выражение *(myArray + i), которое эквивалентно выражению *(i + myArray), которое, в свою очередь, эквивалентно выражению i[myArray]. Настоящие профессионалы знают, как использовать эту особенность в своих целях. Этот способ, к сожалению, применим только в «родных» классах.

28. Если у вас имеется массив из 100 элементов, старайтесь как можно чаще присваивать переменным конкретное значение 100. Не используйте статических ненаследуемых констант вместо этого значения и не ссылайтесь на него через свойство myArray.length. Чтобы это значение было еще сложнее изменить, вы можете использовать другие конкретные числа, к примеру, 50 вместо 100/2 или 99 вместо 100-1. Можно еще больше завуалировать это значение, заменяя выражение a > 100 на a == 101 или выражение a >= 100 на a > 99.

Нужно также учитывать такие особенности, как формат страницы, которая состоит из заголовка x, основного текста y и примечаний z. Вы самостоятельно можете создать путаницу одновременно как в каждой из частей кода, так и в их комбинации или общей сумме.

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

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

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

30. Постарайтесь максимально усложнить структуру кода. Умелые программисты могут вставить до 10 пар круглых скобок ( ) в одной строке и до 20 пар фигурных скобок { } в одном методе. Настоящие мастера умеют располагать начало и конец блока на разных страницах листинга. По возможности в циклах с условием вместо if используйте тернарные операторы [?:].

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

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

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

Никому не говорите, что именно вы изменили в новой версии, если от вас этого не требуются: зачем рассказывать о багах в старой версии, которые никто бы так и не заметил?

33. В разделе «О программе» следует указывать только название программы, имена разработчиков, а также предупреждение о нарушении авторских прав, состоящее из одних юридических терминов. В идеале он должен содержать ссылку на несколько мегабайт кода, которые выдают красивую анимацию. Но ни в коем случае не надо указывать в нем фактическое назначение программы, дополнительный номер версии, дату последнего изменения в программе, сайт, на котором можно получать обновления, или e-mail автора программы. При таком подходе все пользователи вскоре станут работать с разными версиями программы и пытаться установить сразу версию N+2 вместо версии N+1.

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

35. Если вам нужно написать классы, которые будет использовать другой разработчик, вставьте код для проверки переменных окружения (getenv() в C++, System.getProperty() в Java) в статические безымянные инициализаторы ваших классов, а затем передайте в таком виде все свои аргументы классам, вместо того чтобы делать то же самое в конструкторе.

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

36. Выбирайте для переменных названия, не связанные с соответствующими им надписями, которые появляются после запуска программы. Например, если одно из полей на экране подписано как Postal code, то соответствующей переменной вы можете дать название zip.

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

38. Никогда не пользуйтесь менеджерами размещения. Таким образом, когда специалист по сопровождению продукта добавит новое поле, ему придется вручную подбирать абсолютные координаты каждого элемента на экране. Если начальство заставляет вас использовать менеджеры размещения, пользуйтесь одним режимом GridBagLayout, а в качестве координат сетки выбирайте конкретные значения.

39. Забейте на интерфейс Java. Если ваше руководство станет предъявлять к вам претензии, скажите, что интерфейсы Java вынуждают вас копировать код в различные классы, которые одинаково реализуют один и тот же интерфейс, а ваше начальство знает, как тяжело будет сопровождать этот код.

Следуйте примеру разработчиков Java AWT – заполняйте свои классы богатым функционалом, который могут использовать только наследуемые классы, и выполняйте частую проверку в своих методах с помощью оператора instanceof. Получается, что любому, кто захочет несколько раз воспользоваться вашим кодом, придется расширять ваши классы. Если кто-то захочет использовать ваш код из двух разных классов, то им не повезло – они не смогут расширить оба класса одновременно.

40. Определите все свои классы, у которых нет наследников, при помощи ключевого слова final. В конце концов, свою работу на проекте вы выполнили, и никто не сможет его улучшить за счет расширения ваших классов. Более того, это может вызвать проблемы в системе безопасности. Именно поэтому класс java.lang.String объявлен как final. Если другие разработчики на вашем проекте начнут возмущаться, скажите им, что работаете над улучшением производительности программы.

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

42. Храните все неиспользуемые или устаревшие методы и переменные в коде. Если когда-то в 1976 году в них возникала необходимость, что, если она возникнет и на этот раз? Конечно, с тех пор программа сильно изменилась, но все эти изменения можно легко отменить: вы же не станете «изобретать велосипед» (любимая поговорка менеджеров). Если вы оставите в комментариях все эти методы и переменные нетронутыми и не совсем понятными, то все, кто будут сопровождать ваш код, тоже побоятся что-либо менять.

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

44. Измените порядок следования параметров в методе drawRectangle(height, width) на drawRectangle(width, height), не меняя при этом названия самого метода. Затем после нескольких релизов, измените этот порядок обратно. С первого раза очень сложно догадаться, какой из вариантов используется в программе. Оставим задачу понимания работы метода коллегам.

45. Вместо того чтобы передавать параметры в один метод, создайте как можно больше отдельных методов. Например, в методе setAlignment(int alignment)переменная alignment является константой, определяющей выравнивание по левой и правой стороне и по центру. Вместо одного этого метода вы можете создать три: setLeftAlignment, setRightAlignment, и setCenterAlignment. Для еще большего эффекта можете скопировать общий код в каждый из методов, чтобы их сложнее было согласовывать между собой.

46. У метода Камасутры есть особое преимущество: он позволяет рассеять внимание как пользователей и составителей документации, так и специалистов по сопровождению ПО. Создайте множество перегруженных вариантов одного и того же метода, отличающихся друг от друга в незначительных деталях. По-моему, Оскар Уайльд однажды заметил, что в Камасутре позы 47 и 115 отличались лишь тем, что в позе 115 у женщины были скрещены пальцы. Пользователям же приходится тщательно просматривать длинный список методов, чтобы выбрать наиболее подходящий вариант.

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

47. Объявите все методы и переменные публичными. Рано или поздно кому-то это понадобится. Если метод является публичным, от него будет тяжело избавиться: так сложнее будет вносить коррективы в работу программы. Помимо этого, такой подход позволяет скрыть реальное назначение класса. Если начальство начнет к вам придираться, скажите, что вы всего лишь следуете традиционным принципам проектирования «прозрачных» интерфейсов.

48. Перегружайте функции из библиотеки C++, используя директиву #define. В этом случае все будет выглядеть так, будто вы используете функцию, хранящуюся в библиотеке, хотя на самом деле она не имеет к ней никакого отношения.

49. В C++ вы также можете перегружать операции «+», «-», «*»», «/», чтобы выполнять действия, совершенно отличные от сложения, вычитания, умножения и деления. Если уж Страуструп догадался использовать оператор сдвига для осуществления ввода/вывода, разве вы не сможете придумать что-то похожее? Когда перегружаете операцию «+», убедитесь, что выражение i = i + 5; никак не связано с выражением i += 5;

50. При составлении документации для файла лучше подобрать случайное название вроде file, а не такие очевидные имена, как Charlie.dat или Frodo.txt. Если говорить в общем, то старайтесь в своих примерах подбирать случайные названия, максимально похожие на зарезервированные ключевые слова.

К примеру, для названия параметра или переменной отлично подойдут такие варианты, как bank, blank, class, const, constant, input, key, keyword, kind, output, parameter, parm, system, type, value, var и variable. Если в названиях вы используете зарезервированные слова, которые не принимает командный процессор или компилятор, то это еще лучше. Если у вас все получится, пользователи просто запутаются в ключевых словах и выбранных вами названиях, а вы будете здесь ни при чем, потому что хотели лишь помочь им связать назначение каждой переменной с ее именем.

51. Всегда используйте особый синтаксис команд, определяемый вашей собственной версией БНФ (формы Бэкуса-Наура). Никогда не поясняйте значение своего синтаксиса, представленного в виде набора допустимых и недопустимых команд: это будет говорить о низком уровне вашей компетенции. То же касается и использования синтаксических диаграмм.

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

В своей БНФ используйте те же знаки препинания, что и в языке команд: те, кто пытаются разобраться в вашем коде, будут долго думать, составляют ли символы (...), [...], {...} и «...» часть вводимой вами команды или же их цель – показать, какие элементы синтаксиса вашей БНФ обязательны к использованию, какие – необязательны, а какие – просто повторяются. В конце концов, если они настолько глупы, что не могут понять суть вашей БНФ, то им просто нет смысла дальше работать с вашей программой.

52. Препроцессор макросов предлагает много возможностей для того, чтобы запутать тех, кто будет читать ваш код. Основным приемом является размещение макроса на несколько уровней вглубь кода, так что остальным приходится искать его различные компоненты в разных файлах формата *.hpp. Если вы вставите исполняемый код в макросы, а затем поместите эти макросы в каждый из файлов формата *.cpp (даже в файлы, не использующие эти макросы), то вы максимизируете число повторных компиляций, в случае если в код будут внесены изменения.

53. Объявление массивов в Java можно осуществлять разными способами. Вы можете объявлять массив по-старому, как в языках C, в виде String x[] (скобки идут после имени переменной) или по-новому в виде String[] x (скобки ставятся после типа данных). Если хотите окончательно запутать других, то можете смешать оба метода.

54. Java дает возможность запутать других во время преобразования типов переменных. Простой пример: вы, конечно, можете конвертировать тип double в String напрямую через Double.toString(d), но лучше сделать это по-другому, записав new Double(d).toString. Если хотите, можете придумать что-то более изощренное.

Однако не пользуйтесь методами преобразования, рекомендованными в Conversion Amanuensis. Чем больше временных объектов заполняет динамическую память после преобразования, тем лучше.

55. Как можно чаще пользуйтесь потоками.

P.S. Больше материалов по теме стартапов в наших блогах на Geektimes и Megamozg.

Комментарии (118)


  1. alexlash
    02.10.2015 12:03

    Заполняйте код комментариями вроде /* прибавить 1 к i */, но никогда не указывайте в коде такие общие вещи, как назначение модуля или метода.

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


  1. prog666
    02.10.2015 12:11
    +22

    Мне кажется некоторых этому учат в университете.


  1. 1vertus1
    02.10.2015 12:16
    +8

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


    1. Coffin
      02.10.2015 12:25
      +25

      Если бы он использовал все пункты, то до сих пор работал бы с этим кодом, а не вы вместо него :)


      1. mannaro
        02.10.2015 15:11
        +8

        Небось, пошел вверх по карьерной лестнице просто :)


  1. bigfatbrowncat
    02.10.2015 12:21
    +15

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


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


  1. samodum
    02.10.2015 12:29
    -17

    >«вы сможете гарантировать себе пожизненное рабочее место, так как никто кроме вас не сможет разобраться в вашем коде.»

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


    1. bigfatbrowncat
      02.10.2015 12:40
      +11

      Вы, видимо, можете себе это позволить потому что:

      а. У остальных сотрудников достаточная квалификация, чтобы распознать его, пока еще не поздно
      б. У вас достаточно средств, чтобы просто взять и выкинуть из бюджета пару сотен человеко-часов


      1. mapron
        03.10.2015 11:43
        +2

        в. У вас достаточно времени и средств, чтобы найти новых людей и потратить время на их обучение и введение в проект)


  1. AndersonDunai
    02.10.2015 12:29
    +18

    + Используйте кириличные аналоги латинских букв в названиях своих переменных и функций. Это сделает вас неповторимым и загадочным разработчиком.


    1. bigfatbrowncat
      02.10.2015 12:42
      +3

      Кстати, да. Давно жажду, чтобы в популярных ide все символы, не входящие в ASCII, но написанные за пределами комментариев и строковых литералов, как-то особо помечались. Даже в компилирующем языке, порой, можно свести себя с ума, написав «с» или «а».


      1. kahi4
        02.10.2015 13:19
        +2

        Простое решение: шрифт, в котором есть только ASCII, а остальные символы будут тогда отображаться другим. Сразу будет бросаться в глаза.
        И, по-моему, в IDEA можно указать другой (например, bold того же шрифта) для таких символов.


    1. PapaBubaDiop
      02.10.2015 12:48
      +5

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

      1. jopa
      2. gopa
      3. zhoopa

      ?


      1. Mrrl
        02.10.2015 12:55
        +17

        В статье же написали — в разных местах по-разному. Главное, сделать вид, что эти различия на что-то влияют.


        1. REZ1DENT3
          02.10.2015 16:14
          +7

          Кд, нпсннй бз глснх, крч [код, написанный без гласных, короче]

          1. jp
          2. gp
          3. zhp


      1. Halt
        02.10.2015 21:26
        +5

        Очевидно же — использовать язык программирования, который позволяет указывать идентификаторы в UTF-8. Тогда можно написать просто и незатейливо: ??


    1. a553
      02.10.2015 15:58
      +13

      В JetBrains ReSharper у Extension методов первый аргумент зовётся this, где i — украинская буква.



    1. webkumo
      02.10.2015 20:48

      Так легко же заметить… если в остальном слова правильные… ну и если установлена проверка орфографии. :)


  1. Mrrl
    02.10.2015 12:33
    +6

    Половине из этих советов я и так следую. Второй половине следовать не могу, поскольку не пишу на Java.
    Особенно приятно, что в проекте перемешаны углы, выраженные в радианах, градусах, угловых секундах, оборотах и условных единицах, равных 360/2^28 градуса. Иногда также встречаются угловые минуты и устаревшие условные единицы (360/2^15 градуса). Избавиться от них нельзя — они попали в формат одного из конфигурационных файлов…


    1. Mrrl
      02.10.2015 12:37

      Кстати, по поводу пункта 22 — как должен называться единственный открытый статический метод класса, выполняющий всю работу (после рефакторинга Method to Class) — Do или Work?


      1. BloodJohn
        02.10.2015 12:39

        Принято называть InitInstance.


        1. Mrrl
          02.10.2015 12:42

          Так он ничего не Init — он вызывает конструктор (private), потом одну-две функции у полученного объекта, потом возвращает результат — а объект уничтожается.


          1. bigfatbrowncat
            02.10.2015 12:43

            Стоит задуматься о том, чтобы руками и в коде выполнить вот эту операцию:

            объект уничтожается


            А метод перенести в другой класс, где он нужен.


            1. Mrrl
              02.10.2015 12:52

              Смысл метода — что-то вычислить. Скажем, посчитать какую-нибудь сложную характеристику списка точек в пространстве. Вызываться он может из разных мест. Как считает — никому не важно, кроме него самого. Объект нужен, потому что есть много данных, использующися в разных функциях этого вычисления. Но снаружи никто о существовании объекта знать не должен. Так что что-то куда-то выносить, вроде бы, незачем.


          1. BloodJohn
            02.10.2015 12:45
            +4

            Т.е. не соответствует названию. Что и требовалось, коллега.


            1. Mrrl
              02.10.2015 12:53

              Согласен, хорошее обоснование.


      1. mayorovp
        02.10.2015 13:13

        DoWork Run


        1. Mrrl
          02.10.2015 13:17

          Run было бы хорошей идеей, если бы вычисление было асинхронным и запускало отдельный поток.
          Ещё есть Compute.


          1. mayorovp
            02.10.2015 13:34

            Запуск асинхронной операции — это Start или Begin. Run — это именно что проведение операции в текущем потоке…


            1. 1vertus1
              02.10.2015 13:38

              Вот поэтому надо Run!


        1. Leopotam
          02.10.2015 15:34

          Process же.


        1. Stas911
          02.10.2015 15:39
          +4

          БЕГN же!


      1. AndersonDunai
        02.10.2015 15:19
        +3

        Назовите его destroy(). Вот потеха-то будет!


        1. Mrrl
          02.10.2015 15:28

          Encrypt128()


          1. monah_tuk
            02.10.2015 16:23
            +2

            proc1()


            1. mapron
              03.10.2015 11:46

              monsterBoris_collation_128_bit()


      1. Komzpa
        04.10.2015 14:48

        Button1_Click же.


  1. AxisPod
    02.10.2015 12:46
    +7

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


    1. bigfatbrowncat
      02.10.2015 12:56

      Вы — оптимист. Увы, есть гуманоиды с очень особым строением мозга, способные не только сгенерировать нечто, неподвластное представителю homo sapiens, но даже и поддерживать, развивать это и продвигать долго. В мелкой конторе такой человек действительно способен стать «серым кардиналом», которого боится даже учредитель.

      Кажется, Альберт йнштейн сказал (за точность цитаты не ручаюсь):

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

      Под этим углом считать программирование искусством не следует :)


      1. Mrrl
        02.10.2015 12:59
        +5

        Наверное, у них когда-то были хорошие результаты на олимпиадах.


        1. bigfatbrowncat
          02.10.2015 12:59

          Вполне вероятно :)


        1. Rasifiel
          02.10.2015 15:41
          -3

          На любой сколь-либо серъезной олимпиада писать приходится аккуратно и понятно, потому что у вас нет времени вчитываться и пытаться понять.


          1. bigfatbrowncat
            02.10.2015 16:48
            +11

            Если на эту олимпиаду отведено несколько дней, то возможно. Но, в любом случае, олимпиадное программирование — спортивная дисциплина. А в спорте главная задача — прийти первым. В частности — первым выдать верное решение задачи. Любой ценой. Цель «написать красивый код» не ставится. Причем в отличие от коммерческой разработки, где красивый код — вклад в будущее, потому что он упрощает последующую поддержку, в олимпиаде, где вы получите свой приз и навсегда выкините программу, которая вам его принесла, писать код можно как угодно.

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

            Таким образом мы получаем олимпиадника — человека, способного в одиночку ркализовать очень сложный алгоритм и пишущего код по принципу «как можно короче/быстрее». То есть человека, генерирующего сложные алгоритмы в режиме «write-only».


            1. Rasifiel
              02.10.2015 17:07
              +1

              Проблема в том, что если писать как указанно в статье, то ты даже отладить не сможешь в случае чего. Или объяснить сокоманднику что ты там сделал. И с определенного уровня для успеха надо писать аккуратно. Масштаб задач такой, что там для достаточной понятности не требуется декомпозиции, архитектурных решений и прочего такого.
              У меня есть достаточный опыт с людьми у которых «когда-то были хорошие результаты на олимпиадах» (да и сам я какой-то результат имел) и у меня нет проблем с пониманием их кода.


              1. bigfatbrowncat
                10.10.2015 19:32

                Да нет… Увы. Если бы человек, который пишет такой код, сразу был неспособен его отладить, он бы очень быстро бы понял, что делает что-то не так.

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

                Я лично прекрасно помню момент, когда начал впервые задумываться о стиле кодирования. Это произошло в школе, когда мне пришлось дорабатывать прогу, которую я написал для отца за полгода до этого. И там я увидел что-то типа

                for i := 1 to 12 do
                begin
                a[i] := b[i] div 2;
                end;
                Form1.Visible := !Form2.Visible;
                Label12.Text:="Количество";
                

                (код был на Delphi)

                Никаких отступов, комментариев, вообще ничего. Стена из вот такого вот…

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

                Самое интересное, что когда я только создал этого «монстрика», я его прекрасно отлаживал. Я отлично помнил, что значат все эти Form5 и Label126. Так что единственный способ объяснить такому «гению», где именно он неправ — заставить его вернуться к его собственный код полугодовой давности. Или, по меньшей мере, заставить его в течение полугода развивать и поддерживать любое его собственное решение сложнее простого скрипта.

                К сожалению, этот метод дорогостоящий.


          1. faiwer
            02.10.2015 16:53
            +4

            Насколько я помню ACM, человеку страдающему перфекционизмом, в исходные коды лучше не смотреть. Там всё тяп-ляп и на скорость. Как только код проходит тесты (даже если это происходит вопреки ожиданиям), про задачу команда забывает и моментально переходит на следующую. В самом же коде, как правило, никаких классов, наследований и пр. радостей жизни. Просто простыня с методами, если оные оказались нужны. А то и вовсе без них. Например набор одно-буквенных переменных, пяток циклов, чтение и запись файла.


            1. mayorovp
              02.10.2015 18:46

              Как только код проходит тесты (даже если это происходит вопреки ожиданиям), про задачу команда забывает и моментально переходит на следующую.
              Поправка: для того, чтобы программа прошла тесты, надо ее сначала отправить на проверку. А каждая неудачная отправка — это 20 минут штрафного времени. Поэтому программа не может пройти тесты «вопреки ожиданиям», тестируются только те программы, от которых ожидается прохождение всех тестов.

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


              1. zagayevskiy
                03.10.2015 01:14

                Может быть, имелись в виду свои тесты?


  1. faiwer
    02.10.2015 13:17
    +1

    Вспомнилось. Собеседовал как-то человека, который писал примерно вот так (код выдрал из первой попавшейся lib-ы, только переформатировал). Его код напоминал wall_of_text. Т.е. экран был заполнен от края до края кодом на каждой строке. Для того чтобы как-то в этом разбираться, он для разделения блоков кода использовал множественные табуляции (или просто груду пробелов). Долго хвалился тем, какой он опытный перец. Что у него собственный framework и большой пулл довольных клиентов. Робко задал ему вопрос, как у него дела обстоят с MVC, ООП и пр… Он заявил мне, что слышал про это, но в деле не использовал, ибо не особенно то и нужно. Видимо, ему и так удобно. Код он набирал в FAR-е. Мне кажется, я никогда это не забуду :)


    1. dunmaksim
      02.10.2015 13:54
      +4

      Один мой коллега набирает код в FARе (при том 2-м, на 3-ку переходить не хочет принципиально, потому что НЕ НУЖНО). А то напридумывали тут ересь всякую, автоформатирование, подсветка синтаксиса, статические анализаторы какие-то…


    1. Delphinum
      02.10.2015 14:27

      Робко задал ему вопрос, как у него дела обстоят с MVC, ООП и пр… Он заявил мне, что слышал про это, но в деле не использовал

      Мне как то кандидат сказал — я хорошо знаю PHP, я классы пишу!


    1. asm0dey
      03.10.2015 15:30

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


      1. medved13
        06.10.2015 15:36

        А что не так с каррированием?


        1. asm0dey
          06.10.2015 15:40

          Его не понимают. Ну то есть один из коллег считает, что оно увеличивает WTF/s.


  1. vlivyur
    02.10.2015 13:33

    25. сразу вспомнил газовый разряд в универе: есть формула, но без пояснения кто в каких единицах берётся она бесполезна, ибо она эмпирическая.


  1. Karen
    02.10.2015 14:18
    +2

    70 человек добавили статью в закладки :)
    Бомба замедленного дествия получилась.


    1. vlivyur
      02.10.2015 15:49
      +3

      Это чтоб потом почитать.


      1. ZlodeiBaal
        02.10.2015 17:29
        +7

        Вы оптимист…


  1. argz
    02.10.2015 14:28
    +1

    36. Выбирайте для переменных названия, не связанные с соответствующими им надписями, которые появляются после запуска программы.

    label1.text


    1. mapron
      03.10.2015 11:52
      +3

      Да меня как-то попросили подправить очень древнюю расчетную программу на паскале. Так там были
      Label218 и Edit67 или около того) А, еще несколько StringGrid-ов, с фиксированными размерами из которых в куче мест брались параметры (типа константы глобальные) вот так
      StrToDouble(StringGrid4.Cells[2,8]) * Pn + StrToDouble(StringGrid4.Cells[2,9]) * Qn
      и тп


      1. PHmaster
        05.10.2015 00:27
        +2

        Похоже, в паскаль это из экселя переносили


        1. mapron
          05.10.2015 16:11

          вполне, кстати, вероятно.


  1. kanazirsky
    02.10.2015 14:37
    +2

    Вы можете значительно упростить свою программу, если оставите во всем приложении (в методе main) единственный оператор try-catch, который вызывает метод System.exit().

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


    1. poxu
      02.10.2015 17:16

      С появлением средств статистического анализа кода этот метод несколько утратил свою эффективность. Пустые catch блоки слишком просто обнаружить, гораздо лучше выбрасывать в catch новое исключение, никак не связанное с пойманным. Хотя лучше в некоторых случаях всё-таки выбрасывать именно то исключение, которое требует выбросить здравый смысл. Это позволит защититься от программистов, которые просто заменяют все catch блоки нормальными исключениями, не размышляя о том, что может быть на этот раз всё и так было хорошо.


    1. grossws
      02.10.2015 18:29

      И ловить на Throwable, а то мало ли


    1. webkumo
      02.10.2015 21:57
      +1

      Лучше ловить и выбрасывать RuntimeException… через цепочку вызовов, чтобы и по стек-трейсу было не отследить — fatality!


  1. olku
    02.10.2015 14:55

    Запретить эту статью :)


    1. mezastel
      03.10.2015 00:17
      +1

      Пишите в Роскомнадзoр.


  1. MaximChistov
    02.10.2015 14:59
    +3

    Если в методе может выброситься исключение, просто добавьте throws Exception. <3


    1. mayorovp
      02.10.2015 15:01
      +1

      Есть еще более вредный вариант: throws Throwable.


  1. x512
    02.10.2015 15:43

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


    1. khim
      02.10.2015 16:16
      +6

      Ничего страшного. Достаточно немножко потанцевать с define'ами и все ваши автоформаттеры сделают отступы неправильными! Для этого нужно брать define'ы из какиго-нибудь хитрого места, так чтобы автоформаттер до него не добрался и чтобы в них были разбалансированы фигурные скобки — тогда точно «всё будет хорошо» (в смысле обсуждаемой статьи, я имею в виду). Одно нажатие кнопки — и код можно выкидывать :-)


  1. strannik_k
    02.10.2015 16:09

    Столько советов, а простой и надежный способ: «написать функцию с 1000-ей строк кода» — не упомянули :)


    1. khim
      02.10.2015 16:18
      +1

      Потому что он, по большому счёту, совершенно ненадёжен.

      Многое зависит от контекста, но лично мне проще разбираться в функции с 1000-е строк кода, чем с 1000й функций в каждой из которых по одной строке.


      1. Borz
        02.10.2015 16:21
        +1

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


        1. Mirn
          02.10.2015 18:13

          для микроконтроллеров есть такая замечательная либа как uip (миниатюрная реализация TCP)
          случаем не с ней разбирались? Там как раз около 1000 строк кода сдобреное не только обильными If а ещё и лонгджампами, goto и под общим кейсом на почти всё тело в эту 1000 строк кода


          1. Borz
            02.10.2015 18:23

            нет. с Java-кодом — там функция была порядка нескольких сотен строк месива из линейно-древовидных if-else конструкций, сдобренные try-catch конструкциями. Вначале объявлена некая переменная X, которая в процессе наполняется, заменяется, сохраняется в БД, снова наполняется, заменяется, пополняется через вызов других функций и тыдыщ — держите на выходе её некое состояние.


            1. Mirn
              02.10.2015 18:55
              +2

              а у меня была некоторая чудо-функция которая организует TCP сокет с самого низкого уровня — голого набора байт, вплодь до всех фишек обычного TCP, включая весь стек протоколов. Там например вся работа с 32 битными значениями делалась кодом
              b0 += add0;
              if (b0 < add0) b1++;
              b1 += add1;
              if (b1 < add1) b2++;
              b2 += add2;
              if (b2 < add2) b3++;
              b3 += add3
              и вообще все ПОБАЙТНО!
              некоторые сравнения и операции в ПЛИС стиле: линейными логическими операциями сделаные ветвления и циклы.
              ты видишь вложенное условие с проверками и арифметикой? нет? Там только логика? а всё это там есть!
              Они даже умудрились напрочь скрыть настройку MTU и прочих фишек, ниодной константы и действия связанного с этим не нашол. Даже комментируя блоки — всё равно работает.
              А для чего я это ковырял: отключить алгоритм нагля, сделать нормальное TCP окно и прочие твики чтоб можно было передавать данные быстрее 1кбайта в сек.


              1. Mrrl
                02.10.2015 19:17

                b0 += add0;
                if (b0 < add0) b1++;
                b1 += add1;
                if (b1 < add1) b2++;

                Здесь b0,b1,b2 — это unsigned char?
                И что же она сделает, если b0=add0=0x80, b1=0xFF, add1=0x01?
                После первого сложения будет b0=0;
                Первая проверка покажет, что было переполнение;
                b1 увеличится на 1 и станет равным 0x00;
                После второго сложения он будет 0x01;
                И вторая проверка покажет, что переполнения не было.
                Это действительно то, что ожидалось?


                1. Mirn
                  02.10.2015 19:21

                  извините, по памяти писал. накосячил малость

                  сейчас (исходник uip с гитхаба) код выглядит так:
                  uip_acc32[3] = op32[3] + (op16 & 0xff);
                  uip_acc32[2] = op32[2] + (op16 >> 8);
                  uip_acc32[1] = op32[1];
                  uip_acc32[0] = op32[0];

                  if(uip_acc32[2] < (op16 >> 8)) {
                  ++uip_acc32[1];
                  if(uip_acc32[1] == 0) {
                  ++uip_acc32[0];
                  }
                  }


                  if(uip_acc32[3] < (op16 & 0xff)) {
                  ++uip_acc32[2];
                  if(uip_acc32[2] == 0) {
                  ++uip_acc32[1];
                  if(uip_acc32[1] == 0) {
                  ++uip_acc32[0];
                  }
                  }
                  }

                  раньше выглядел как то похоже на то что я написал ранее выше


                  1. Mrrl
                    02.10.2015 19:37

                    Так нужно к 32-битному числу прибавить 16-битное?
                    Казалось бы,

                    a0+=b0;
                    c=(a0<b0 && ++a1==0);
                    a1+=b1;
                    if((c || a1<b1) && ++a2==0) ++a3;

                    К a3:a2:a1:a0 прибавляется b1:b0


                    1. Mirn
                      02.10.2015 19:44

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


  1. alexus_ru
    02.10.2015 17:07

    Надо добавить: “как можно больше используйте рефлексию, желательно все вызовы других методов перевести на поиск метода по строковой константе имени объекта и метода и вызов посредством рефлексии. А все объекты — синглтоны"


    1. Sirion
      05.10.2015 08:44
      +1

      Это уже есть в JS.


  1. anatoly314
    02.10.2015 18:23

    Есть еще одна малоизвестная хитрость, использовать следующую конструкцию:

    try{
        ...
        code here
         ...
    }catch(Exception e){}
    


    1. Borz
      02.10.2015 18:29
      +1

    1. Starche
      02.10.2015 20:50

      try{
          ...
          code here
           ...
      }catch(Exception e){
          //If something went wrong
          //Let it go silently
      }
      


      1. anatoly314
        02.10.2015 20:51
        +2

        Мне больше нравится такой вариант :)

        try{
            ...
            code here
             ...
        }catch(Exception e){
            //Who cares?
        }
        


        1. adombrovsky
          02.10.2015 22:38

          try{
              ...
              code here
               ...
          }catch(Exception e){
              //Houston we have a problem
          }
          


  1. ingumsky
    02.10.2015 18:47
    +5

    Ого! Григорий Остер подался в программирование!


  1. UA3MQJ
    02.10.2015 18:48

    Я из тех же соображений пообещал работодателю, что все новые разработки теперь буду вести исключительно на Erlang. Еще можно попробовать писать скрипты для каких-либо расчетов на Verilog.


    1. Mirn
      02.10.2015 19:41
      +1

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

      Написал на Си но в ПЛИС стиле,.
      Плис стиль в том что
      1. Все логические и арифметические операции сведены к логическим базису И-НЕ. Остаются только пересылки и индексации, особенно монстроидальное умножение хоть и 8 бит но это нечто если глянуть асм листинг! особенно в сигнальной обработке.
      2. Все функции в строгом инлайне
      3. Ветвления делаются так:
      было
      if (cond)
      a=b;
      else
      a=c;

      стало
      a = (cond and b) or (not cond and c)
      4. Так же делаются автоматы (на счётчиках и сдвиговых регистрах)
      5. Циклы разворачиваются
      естественно с доработкой операций до и-не базиса
      написал естественно нормальный алгоритм на си, сделал юнит тест, сделал в плис стиле с использованием инлайн функций и оформил нормально.

      все это в функции которая вызывается для каждой выборки из АЦП
      .
      Даже написал мануал из каментов по каждой строке чтоб самому потом не напороться…
      Напоролся…
      коллега которому досталось сказал следующее:
      <5 минут мата>,
      смысл в юнит тестах, описания?, если я стаким стилем не знаком!
      <ещё пара минут мата>
      ты вообще асм листинг смотрел? я думал что знаю асм!
      <мат>

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

      больше так не буду никогда!
      не делайте так, пожалуйста!


      1. Mrrl
        02.10.2015 22:44

        1. Все логические и арифметические операции сведены к логическим базису И-НЕ.

        Любопытно.
        while(b){
        c=a&b;
        a=~c&(~(~a&~b)); // a^b
        b=c<<1;
        }
        будет выполняться до 8 раз (для случая a=1, b=0xFF). Можно ли быстрее?


  1. kt97679
    02.10.2015 20:29

    Старый текст на ту же тему: http://www.lightnet.obninsk.ru/Review/Relax/diag_prog_11.shtml


  1. andrewnester
    02.10.2015 22:44
    +2

    для c++ есть классный советик

    #define if(x) if(x && (rand() % 10 == 0))


    1. mezastel
      03.10.2015 00:19
      +3

      Может лучше != чтобы сложнее было поймать?


      1. andrewnester
        03.10.2015 12:00

        да! абсолютно верно, опечатался, спасибо, что заметили


  1. SamSol
    03.10.2015 21:04
    +5

    56. Сделайте несколько псевдонимов для метода.

    function open() {
    ...
    }
    function close() {
    ...
    }
    
    module.exports = {
        open: open,
        close: close,
        show: open, // <---- WTF?!
    }
    

    Объясняйте это тем, что иногда забываете конкретное имя метода. run(), start(), do()? или open(), show(), display().


  1. mrjj
    03.10.2015 22:01
    +3

    Также, ни в коем случае не доверяйте системы управления версиями хранить историю изменений, смело создавайте MyClass2, MyClass3, MyClass2014, MyClass2015, MyClassAdvanced, MyClass3New, MyClass3Newest, MyClass2To3Compat и используйте их одновременно. При этом не надо использовать никаких фасадов, они только усложнят решение.
    Еще лучше будет расположить эти классы в файлах с собственной и отличной от классов нумерацией.


  1. jee
    06.10.2015 13:32

    Шедеврально, посмеялся какследует, спасибо :D


  1. vbif
    06.10.2015 14:20

    В дополнение к 19 совету: полю или глобальной переменной обязательно нужно дать имя вроде «temp», «aux», а ещё лучше «s1», «sss», «a». Но это не всё: нужно обязательно использовать значение этой переменной через несколько сотен строк после присвоения. А лучше в другом методе.


    1. vbif
      06.10.2015 14:54
      +1

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


      1. Mrrl
        06.10.2015 16:58
        +1

        Почему при старте? Инициализируем по мере появления соответствующих значений. Желательно, из разных модулей программы.


        1. vbif
          06.10.2015 20:55

          Такой способ имеет ограниченное применение: нужно быть уверенным, что все эти значения уже присвоились, иначе может выскочить ошибка в моём коде, и ругаться будут на меня. А так я соблазняю новичка, которому потребуется воспользоваться объектом того же класса не делать утомительную инициализацию нового объекта, а воспользоваться готовым проиницализированным, которому останется чуть-чуть изменить значение какого-то поля.


    1. jee
      06.10.2015 14:55

      Да просто используйте глобальные переменные, этого достаточно =)


      1. vbif
        06.10.2015 15:14

        Да ну вас, это слишком банально ;)


  1. vbif
    06.10.2015 15:06
    +1

    По комментариям: нужно писать их в таком формате:

    ...
    code;
    
    //Этот блок кода делает (это и это)
    
    
    code;
    ...
    

    Тем, кто будет спрашивать, о каком блоке кода речь идёт в комментариях — объяснять, что к тому, от которого отбит меньшим количеством строк. (неужели не понятно?). Самому это правило соблюдать не нужно.


  1. alexraven
    06.10.2015 20:26

    Когда я начинал программировать, никакого Unicode не было. Я про него впервые узнал из Dr. Dobb's Journal за 1994 (кажется) год и немного недоумевал: кому и зачем в реальной жизни это может понадобиться? А тут, оказывается, можно греческий вопросительный знак вместо точки с запятой поставить. А сегодня мне трудно себе представить, что я редактирую исходники в чем-то, отличном от UTF-8 :-)


  1. alexraven
    06.10.2015 20:58

    По возможности в циклах с условием вместо if используйте тернарные операторы [?:]

    Отличный совет! В комбинации с отсутствием комментариев и ничего не значащими именами переменных, является отличной тренировкой для твоего последователя на логику и внимание. То же самое относится и к SQL инструкциям.

    function _ll(a){return((a%400)==0)?1:(((a%100)==0)?0:(((a%4)==0)?1:0))}
    


    1. Mrrl
      07.10.2015 00:53

      Это ужастно. Не лучше ли так:

      return a%4 && (!(a%100) || a%400);

      Короче, но внимания требует не меньше.


      1. mayorovp
        07.10.2015 06:04
        +1

        Как это — «не меньше»? Я, к примеру, по этой формуле сразу же понял, что она делает. В отличии от формулы выше, которую не стал разбирать испугавшись количества скобочек :)


        1. Mrrl
          07.10.2015 08:04

          А я там скобочек даже не видел, смотрел только на буквы и цифры. Всё было понятно.
          Хотя если бы формула делала не то, что кажется на первый взгляд, например, (((a%400)==0)?1:(a%100)==0) выступало бы условием для следующего оператора, было бы интереснее.

          uint ETA = (a <= b ? (a <= c  && c < b) : (a <= c || c < b)) ? b-c : 0;


          1. mayorovp
            07.10.2015 08:41

            Так в том-то и дело, что просто так код не смотрят. Смотрят код, когда ищут ошибку. «Короткий» вариант я не только понял, но и быстро проверил. «Длинный» же сходу проверить не получится.


      1. hopungo
        07.10.2015 11:54

        Вы нам работу застопорили :) Я сразу догадался, что это

        посмотреть ответ
        григориан


  1. hopungo
    07.10.2015 09:41

    Я бы ещё добавил сюда пункты «хранить данные в коде, системный код и код, выполняющий важные задачи, выносить в скрипты и сторонние библиотеки, а бизнес-логику писать на ассемблере. Вообще желательно писать всё шиворот-навыворот, нагромождая как можно больше парадигм и технологий, чтоб никто ничего не смог понять.»


    1. Mirn
      07.10.2015 11:00

      Самое плохое что, подобный совет я на полном серьёзе иногда слышу от разных программистов, при этом добавляют: «иначе ты никогда не получишь прибавку к зп или тебя вообще заменят на студента». И не только из гос-контор и не только от наших программистов.


      1. hopungo
        07.10.2015 11:35

        Тут уже больше от работодателя зависит. Хороший работодатель понимает, что студент набыдлокодит и уйдёт, а ответственный программист будет ценить, что ему дают возможность сделать красиво и правильно, и вряд ли где ещё дадут.