Признаки плохого программиста

http://badprogrammer.infogami.com/
  • Перевод

Неспособность рассуждать о коде


«Рассуждать о коде» значит понимать порядок исполнения инструкций («исполнять программу в голове»), зная, каково предназначение кода.

Симптомы

  • Наличие «волшебного», «вуду» кода или кода, который не имеет никакого отношения к целям программы, но всё равно тщательно поддерживается (например, инициализация переменных, которые никогда не используются, вызов функций, не имеющих отношения к цели, создание выходных данных, которые не используются, и т.д.).
  • Многократные вызовы идемпотентных функций (например, вызов save() по нескольку раз, «чтобы уж точно»).
  • Исправление ошибок написанием избыточного кода, который замещает данные, полученные при исполнении неисправного кода.
  • «Йо-йо код», который конвертирует значения в различные представления, а потом конвертирует их обратно ровно в то же представление, с которого начинали (например, преобразование десятичного числа в строку, а потом обратно в десятичное число, или padding строчки с последующим trim'ом).
  • «Бульдозерный код», который создает впечатление рефакторинга посредством разбития кусков кода на процедуры, которые, правда, затем невозможно использовать где-либо еще (высокая когезия).


Лечение

Чтобы справиться с этим пороком, программисту следует пользоваться встроенным в IDE debugger'ом как помощником в случае неспособности «шагать» по коду построчно. В Visual Studio, например, можно установить breakpoint в начале «проблемной» зоны и затем шагать, нажимая F11, параллельно следя за значениями переменных, до тех пор пока не станет ясно, что именно код делает. Если в целевом окружении нет такой возможности, следует практиковаться в том, в котором это возможно.

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

Плохое понимание модели языка программирования


Объектно-ориентированное программирование — пример модели языка программирования, равно как и функциональное, и декларативное программирование. Все они существенно отличаются от процедурного или императивного программирования, точно так же как и процедурное программирование существенно отличается от ассемблера или программирования с помощью GOTO-инструкций. Также существуют языки, которые следуют какой-то распространённой модели программирования (скажем, объектно-ориентированному программированию), но вносят в неё какие-то усовершенствования, как например генераторные выражения (list comprehensions), обобщенное программирование (generics), утиная типизация (duck typing) и т.п.

Симптомы

  • Использование любого необходимого синтаксиса для того, чтобы «вырваться» из предлагаемой языком модели, и написание оставшейся части программы в императивном/процедурном стиле.
  • (ООП) Попытки вызова не статических функций или присвоения переменных в неинстанциированных классах, проблемы с пониманием, почему такие конструкции не компилируются.
  • (ООП) Наличие огромного количества «....Manager» классов, которые содержат все методы манипуляции с объектами, которые, в свою очередь, совсем не содержат (или содержат мало) методов.
  • (Реляционное) Обращение с базой данных как с хранилищем объектов, исполнение всех JOIN'ов и проверки целостности на клиентской стороне.
  • (Функциональное) Создание многих версий одного и того же алгоритма для обработки разных типов или операторов вместо передачи функций высшего порядка обобщенному алгоритму.
  • (Функциональное) Ручное кэширование результатов детерминистических функций на платформах, которые делают это автоматически (SQL или Haskell).
  • (Функциональное с «чистыми»(pure) функциями) Использование копипасты из чужого кода для того, чтобы побороть I/O и монады.
  • (Декларативное) Установление индивидуальных значений в императивном коде вместо использования связывания данных (data binding).


Лечение

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

Шаг 1: «ООП — это просто структуры с методами».
Шаг 2: «Методы в ООП — это просто функции, исполняющие мини-программу со своим собственным набором глобальных переменных».
Шаг 3: «Глобальные переменные называются полями, некоторые из них приватные и невидимы снаружи мини-программ».
Шаг 4: «Сама идея наличия приватных и публичных элементов — скрыть детали реализации и выставить наружу чистый интерфейс, и называется это инкапсуляция».
Шаг 5: «Инкапсуляция означает, что моя бизнес-логика не должна засоряться деталями реализации».

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

Шаг 1: «Функциональное программирование — это когда всё делается через цепочки детерминистических функций».
Шаг 2: «Когда функции детерминистические, их не нужно вычислять до тех пор, пока это не потребовалось в выходных данных, и вычислять необходимо только ту часть, которая действительно потребовалась. Это называется ленивыми и частичными вычислениями».
Шаг 3: «Для того чтобы поддерживать ленивые и частичные вычисления, компилятор требует, чтобы я писал функции в терминах трасформации одного параметра, иногда делая результатом таких преобразований другую функцию. Это называется каррированием (currying)».
Шаг 4: «Когда все функции каррируемы, это позволяет компилятору выбрать наилучший план исполнения с помощью constraint solver'а».
Шаг 5: «Позволяя constraint solver'у самому решать все неважные детали, я могу писать программы, описывая, что я хочу, а не как именно это получить».

Дефицит исследовательских навыков / Хронически плохое знание возможностей платформы



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

Симптомы

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

  • Изобретение или создание механизмов, которые уже встроены в язык, например, event'ы и handler'ы, регулярные выражения.
  • Изобретение классов и функций, которые уже есть в фрэймворке (например, таймеры, коллекции, алгоритмы сортировки и поиска).*
  • Сообщения «Напишите мне код, плиз!» в различных форумах.
  • «Окольный код», который выполняет свою задачу с гораздо большим количеством инструкций, чем требуется (например, округление числа через преобразование к строке и обратно).
  • Постоянное использование старомодных техник, даже если новые лучше в текущей ситуации (например, создание полноценных именованных функций там, где нужно лямбда-выражение «на раз»).
  • Нереального размера «зона комфорта», когда человек готов пройти экстремально длинный путь, решая проблему примитивными средствами.

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

Лечение

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

Неспособность понять указатели


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

Симптомы

  • Неспособность написать связный список, или написать код, который вставляет/удаляет узлы из связного списка без потерь данных.
  • Выделение произвольных больших массивов для данных переменного размера вместо связных списков или других динамических структур данных.
  • Неспособность найти или исправить ошибки, связанные с арифметикой над указателями.
  • Изменение разыменованных значений из указателей, переданных в функцию, без понимания, что это измененит значения за пределами области действия (scope) функции.
  • Создание копии указателя, изменение разыменованного значения через копию с ожиданиями, что оригинальный указатель по-прежнему указывает на старое значение.
  • Сериализация указателя, в то время как сериализовано должно быть разыменованное значение.
  • Сортировка массива указателей сравнением самих указателей, а не значений.

Лечение

Мой друг Джо жил в том же отеле, что и я, но я не знал, в каком именно номере. Однако я знал, где остановился его знакомый Фрэнк. Так что я пошел туда, постучал в дверь и спросил Фрэнка: «Где остановился Джо?». Фрэнк не знал, но он знал, в какой комнате живет Теодор, коллега Джо. Так что я пошел в комнату Теодора и спросил, где остановился Джо, и Теодор сказал мне, что Джо в комнате 414. Там-то я его и нашел!

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

Сложности с рекурсией


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

Симптомы

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


Лечение

Закатайте рукава и будьте готовы к переполнениям стэка. Начните с написания функции с одним основным условием и с одним рекурсивным вызовом, который использует тот же, не изменённый аргумент, что и был получен на входе. Остановитесь, даже если вам кажется, что этого недостаточно, и запустите. Посмотрите на переполнение стэка, вернитесь обратно и добавьте изменение аргумента при рекурсивном вызове. Опять переполнение? Чрезмерный вывод? Тогда еще несколько итераций, переключаясь между изменениями в условии и в вызове, до тех пор, пока вы не начнете чуять, как функция трасформирует входные данные. Сопротивляйтесь желанию использовать более чем одно основное условие или более чем один вызов, если вы не знаете, зачем вы это делаете.

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

Признаки заурядного программиста



Неспособность мыслить коллекциями


Переход от императивного программирования к функциональному и декларативному потребует от вас способности думать об операциях над наборами данных. Коллекции станут вашим примитивом вместо скалярных значений. Это требуется, если вы используете SQL и реляционные базы данных, если вы разрабатываете программы, которые должны маштабироваться пропорционально количеству ядер процессора, или когда вы пишете код, который будет запускаться на SIMD-чипах (как, например, современные графические карты и игровые приставки).

Симптомы

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

  • Исполнение атомарных операций над элементами коллекции внутри цикла for или foreach.
  • Map или reduce функции, содержащие циклы для итерации по набору данных.
  • Получение большого набора данных с сервера и вычисление сумм на клиенте, вместо использования агрегирующих функций в запросе.
  • Написание функций бизнес-логики с трагическими сайд-эффектами, вроде изменения пользовательского интерфейса или выполнения I/O функций.
  • Классы сущностей, которые открывают свои собственные соединения с базой данных или получают файловые дескрипторы и держат их активными всё время жизни каждого из объектов.


Лечение

Представляйте себе дилера в казино, который сдвигает колоду карт и перемешивает две части вместе пролистыванием, это может подтолкнуть вас к размышлениям о коллекциях и о том, как вы можете оперировать ими. Другие стимулирующие визуализации:
  • въезд на платную дорогу, оборудованный несколькими пунктами оплаты (параллельная обработка);
  • ручейки, которые соединяются в потоки, которые соединяются в рукава, из которых получается река (парралельное исполнение reduce / агрегирующие функции);
  • застёжка-молния (простые join'ы);
  • траспортная РНК, собирающая аминокислоты и соединяющаяся с информационной РНК внутри рибосомы, чтобы стать протеином (многостадийные funtion-driven join'ы);
  • то же самое, происходящее в миллиардах клеток в апельсиновом дереве, чтобы превратить почву, воду и солнечный свет в апельсиновый сок (map/reduce в больших распределенных кластерах);

Если вы пишете программу, которая работает с коллекциями, подумайте обо всех дополнительных данных и записях, которые необходимы вашим функциям для того, чтобы работать над каждым из элементов. Используйте map-фукции для того, чтобы соединить их в пары, до того, как вы примените к каждой из этих пар reduce.

Отсутствие критического мышления


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

Симптомы

  • «Движки бизнес-правил».
  • Толстые классы со статическими утилитами, или библиотеки, решающие множество разных задач, но имеющие одну область имён (namespace).
  • Архитектуры, которым начали требоваться эпициклы.
  • Добавление в таблицы колонок для не имеющих прямого отношения к этой таблице данных.
  • Несоблюдение однородности в именовании переменных и методов.
  • Ментальность «мужика с кувалдой», или изменение условий задачи так, чтобы она могла быть решена с помощью одной конкретной технологии.
  • Программы, которые своей сложностью затмевают задачу, которую они должны решать.
  • Патологическое и излишнее «защитное» программирование (defensive programming), «энтэрпрайзненький код».

Лечение

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

Когда вы привыкнете к тому, что другие люди изучают, проверяют ваши идеи, начните всесторонне изучать свои идеи самостоятельно. В дополнение, вам необходимо развить чувство пропорции (чтобы понимать, насколько дизайн подходит размеру задачи), привычку проверять предположения (чтобы вы не переоценивали размер задачи), и здоровое отношение к неудачам (Исаак Ньютон был неправ про гравитацию, но мы всё равно любим его, и его предположения очень важны для нас).

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

Пинбол-программирование



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

Симптомы

  • Один try-catch блок, включающий в себя всё тело Main(), рестартующий программу.
  • Использование строк или целых чисел для значений, которые могли бы иметь более подходящий им тип в языке со строгой типизацией.
  • Упаковка сложных данных в разделённые строчки и их парсинг в каждой функции, где эти данные используются.
  • Неспособность использовать утверждения или контракты методов на функциях, которые делают предположения о своих аргументах.
  • Использование sleep() для ожидания пока другой thread закончит свою работу.
  • Инструкции Switch над неперечисляемыми значениями без блока «иначе».
  • Использоватие automethod'ов или reflection'ов для вызова методов, исходя из неподготовленного пользовательского ввода.
  • Использование глобальных переменных для возврата из функции более одного значения.
  • Классы с одним методом и набором полей, которым необходимо установить значения, по сути, для передачи параметров в метод.
  • Обновление связанных данных в БД без использования транзакций.
  • Попытки восстановить состояние базы данных без транзакций и rollback.

Лечение

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

Вам нужно ознакомиться с механизмами вашей платформы, которые позволяют сделать вашу программу надёжной и пластичной. Три основных вида таких механизмов:
  • Те, что останавливают исполнение программы до того, как причинён какой-либо ущерб тем, что произошло что-то неожиданное, а потом помогают вам определить, что именно пошло не так (системы типов, assert'ы, exception'ы).
  • Те, что направляют программу по пути, который наилучшим образом обрабатывает неожиданности (try-catch блоки, мультиметоды (multiple dispatch), событийно-ориентированное (event-driven) программирование).
  • Те, что приостанавливают thread до достижения необходимого состояния (инструкции WaitUntil, мьютексы и семафоры, SyncLock'и).

Есть ещё и четвёртый механизм — unit тестирование, которое вы используете во время проектирования и разработки.

Использование этих механизмов должно быть для вас так же естественно, как и расстановка запятых в предложении. Чтобы достичь этого, пройдитесь по перечисленным в скобках механизмам и отрефакторьте какую-нибудь старую программу так, чтобы она использовала их везде, где только сможете их пристроить, даже если это окажется неприемлемым (особенно если это окажется неприемлемым, только так вы начнёте понимать почему).

Незнание принципов безопасности


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

Симптомы

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


Лечение

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

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

Далее, проверьте запросы к базам данных, которые конкатенируют неизменённые входные данные в SQL запрос, и перепишите этот код с использованием параметризированных запросов, если это позволяет ваша платформа. Ну, или добавьте фильтрацию/экранирование всех входных данных, если нет. Это чтобы предотвратить атаки с SQL-инъекциями.

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

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

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

Во-первых, вы не должны доверять коду или другому криптографическому примитиву, если он не опубликован открыто и не был проанализирован и опробован сообществом. Нельзя достичь безопасности через неясность (security through obscurity), через проприетарность или через новизну. Реализации пусть даже заслуживающих доверия криптографических примитивов могут иметь изъяны, потому избегайте реализаций, которые не были тщательно изучены. Все новые криптографические системы попадают в «трубопровод» исследований длиною в 10 лет или более, и вам хорошо бы использовать те из них, что уже показались с другой стороны этой «трубы» невредимыми.

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

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

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

Признаки того, что вам не стоило бы быть программистом


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

Неспособность определить порядок исполнения программы



Симптомы

a = 5
b = 10
a = b

print a

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

Альтернативные профессии

  • Электрик
  • Слесарь
  • Архитектор
  • Инженер-строитель


Неспособность мыслить абстрактно



Симптомы

  • Сложности с пониманием различия между объектами и классами.
  • Сложности реализации шаблонов проектирования в ваших программах.
  • Сложности написания функций с низкой когезией.
  • Некомпетентность в регулярных выражениях.
  • LISP для вас непостижим.
  • Не можете понять тезис Чёрча-Тьюринга.


Альтернативные профессии

  • Уполномоченный по согласованию контрактов
  • Актёр


Синдром Плюшкина



Симптомы

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

Альтернативные профессии

  • Торговец антиквариатом
  • Бездомный с огромной тележкой хлама


Нарушение причинно-следственных связей



Симптомы

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

Альтернативные профессии

  • Завсегдатай заведений с игровыми автоматами


Безразличие к результату


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

Симптомы

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

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

Альтернативные профессии

  • Специалист по взысканию задолженности
  • Телемаркетинг
Метки:
Поделиться публикацией
Похожие публикации
Комментарии 260
  • +176
    Боже, сколько букв… Если я все прочту, я стану хорошим программистом?
    • +43
      Хуже точно не станете.
      • +33
        Станете хорошим если будете много писать кода, а так эта статья сродни GTD-статьям — вроде все правильно, а все равно читать это в сотый раз уже опостылело.
        • +3
          Можно всю жизнь писать очень плохо плохого кода. А можно — прочитать хоть раз подобную статью и задуматься.
          • +2
            Я вот тоже после каждой статьи про «правильный» код, про «правильное планирование» задумываюсь — только вот результаты у меня улучшаются только после того как я делать что-то начинаю, а чаще переделывать.

            Если этот код никому не сдавать, не находить в нем баги, не делать саморевизии, делать все время разные задачи, то ясен перец, что какашка будет выходить. Но дважды написать какашный код для одной и тоже задачи — нонсенс.
            • +1
              А Можно пойти работать в компанию где практикуется code review и следование корпоративному(проектному) code convention и начать писать лучше уже после первого же ревью
              • +1
                Одно другому не мешает, разумеется. Есть куча способов писать хорошо. Но code review не сможет дать понятия, например, чем класс отличается от объекта, и прочим неочевидным вещам не научит. Игнорирование последних может научить «писать так, потому что я так вон там видел».
              • –2
                точно, без статьи никак:)
                • –2
                  Задуматься и продолжить писать «очень плохо плохого кода».
                  • +1
                    Тогда не понятно, по какой причине вообще человек пишет код.

                    И какой смысл был указывать на мою опечатку? Вроде общеизвестно, что комментарии исправлять нельзя, но, немного пораскинув мозгами, можно дойти до того, что вместо «плохо» должно стоять «много». Или Вы намекаете, что я должен был написать еще один комментарий, с принесением извинений всем, чью психику я потревожил?
                • +1
                  В отличии от статей по GTD, тут указаны конкретные ошибки, типа слабое знание платформы, не использование _название_фичи_ и пр. Вдруг кому-то поможет? Мясо явно больше, чем в большинстве статей по GTD.
                • +7
                  Вас просто могут уволить за то что вы читаете вместо работы ;)
                  • +1
                    Да тут прямо руководство «как надо жить»
                    • НЛО прилетело и опубликовало эту надпись здесь
                    • +1
                      Ну и, по традиции, привели бы кратенький список литературы по типу “Как стать хорошим программистом”
                      • 0
                        А также источник сведений о существовании в Haskell поддержки кэширования результатов вызова функций. Google выдаёт ссылку на Stack Overflow, где обсуждается эта тема и говорится, что в Haskell этой возможности нет.
                      • +2
                        Все не осилил. Надо будет прочитать. При взгляде не код вспоминается «краткость — сестра таланта». Это и к программистам тоже применимо :).
                        • +4
                          Я думаю, если учесть весь жизненный опыт, на котором основана статья, то процент сжатия информации получится неплохой. Вы когда мануал читаете к дремучему SDK, тоже жалуетесь на объем? =)
                        • +4
                          Исправление ошибок написанием избыточного кода, который замещает данные, полученные при исполнении неисправного кода.
                          =============
                          вот тут не соглашусь — это не всегда какой то симптом — часто это старый чужой проект в котором тебе дали быстренько пофиксить какую-то проблему
                          • 0
                            А мне позвольте не согласиться с Вами: даже если это «старый чужой проект», нельзя исправлять ошибки таким образом. Впоследствии после Вас может придти следующий человек, которому «дали быстренько пофиксить какую-то проблему», и в итоге ничего хорошего не получится.
                            • +5
                              проекты бывают разные, как и клиенты… бывают правки за которые никто не заплатит при этом искать ошибку можно несколько дней
                              • +10
                                В идеальном сферическом мире, возможно, так и должно быть. А в реальном мире никто не знает, как именно этот код работает. Документации нет. Тесты? Не, не слышал. Сроки ограничены. В результате лезть глубоко просто тупо страшно, да и некогда.
                            • +13
                              Бррр… Я по ходу эт… пошел вешаться...(
                              • +3
                                Я в фаербаге это проверил:

                                a = 5
                                b = 10
                                a = b

                                У меня есть надежда :)

                                • +2
                                  Надо в голове, без фаербагов, тогда будет надежда ;-)
                                  • +3
                                    … О НЕЕЕЕЕТ :((((
                                    Не вышло короче. AlexRed, подождите, вместе пойдем.
                                  • +1
                                    у человека есть смекалка-значит не все потеряно
                                    • 0
                                      А еще ответом может быть «0» (в смысле False) :)
                                      • –1
                                        Охренеть. Если не Ваш коммент, так бы и думал, что ответ 5 и задача для дураков.
                                        Всё, спать пора. Или в отпуск.
                                        • –2
                                          Так, тренировка на класической задаче обмена
                                          a = 3
                                          b = 2
                                          a = b + a
                                          b = a — b

                                          Вроде ещё сгожусь.
                                          Всё, спать.
                                          • –1
                                            А вот нет.
                                            a = 3
                                            b = 2
                                            a = b + a
                                            b = a — b
                                            a = a — b

                                            Вот теперь всё. Точно спать.
                                            • –3
                                              var a = 3
                                              var b = 2
                                              function(){
                                              c=a
                                              a=b
                                              b=c
                                              }()

                                              Хватит с эти, завязываю. Спать.
                                          • 0
                                            а как там 5 вообще могло получиться?
                                          • 0
                                            Результат зависит от языка. Вдруг оператор присвоения перегружен?
                                          • 0
                                            а там везде альтернативные профессии указаны, вешаться не обязательно!
                                          • 0
                                            ну не компетентен я в регулярных выражениях и lisp не знаю и о боже prolog и brainfuck, а на кой черт они мне для написания например приложений на том же C/С++.
                                            • –9
                                              Я ненавижу регулярные выражения. У них синтаксис какой-то забубенный, нечеловеческий…
                                              • +6
                                                Используйте #define Все_заглавные_буквы_ASCII \A-Z
                                                • +6
                                                  Есть такая шутка:
                                                  Если у вас есть проблема, и вы собираетесь решать ее с использованием регулярных выражений, то у вас есть две проблемы.

                                                  Но на самом деле штука просто замечательная, к тому же применима для запугивания неподготовленных людей. Показываешь им строчку кода с каким-нибудь замудрёной регуляркой, а тебе в ответ: «Едрить, магия какая-то!».
                                                  • +3
                                                    Проблемы начинаются, когда регулярными выражениями начинают решать не те задачи. Мне однажды попался класс, где вся работа со стоками была сделана на регулярках. Это было ужасно.
                                                  • +1
                                                    Самое смешное, что синтаксис у них довольно таки человеческий :) Легенды гласят, что регулярки придумали для описания процессов в нервной системе человека (тыц)
                                                  • +1
                                                    возможно автор имел в виде «способность всосать»
                                                    • +4
                                                      не компетентен я в регулярных выражениях
                                                      Зря, очень зря. Их надо знать хотя бы для перемалывания тонн текста через grep и sed.
                                                      • +4
                                                        Не у всех есть такие задачи. А некоторые даже сидят на (о боже!) виндоусе :-)
                                                        • +1
                                                          сижу на винде, но без православных sed и grep жить не смог, скачал их для win32
                                                          а затем подтянул архив с bash'ем, включая эмулятор терминала, теперь радуюсь нормальной консоли в винде
                                                          • 0
                                                            Скачивал я как-то цыгвин. Не понравился мне тамошний терминал. Хотя это было N лет назад, может уже и получше стал :-)
                                                            • 0
                                                              цигвин на виндовом терминале работает, у меня так же можно просто bash выполнить и получить консоль баш с ограничением по ширине и кривой кодировкой. А в эмуляторе все норм.
                                                              т.е. если я хочу попасть в русский линух то нужно пользоваться putty, а в иностранный можно прям с консоли ssh name@host
                                                              + авторизация по ключам работает из каталога ~/.ssh
                                                              • 0
                                                                И что, прям настоящий терминал? Без проблем с копированием/вставкой текста?

                                                                И чем русский линукс от буржуйского отличается? Там sshd другой? :-)
                                                                • 0
                                                                  Там кодировки с cmd не совместимы
                                                                  А проблем нет. Даже ктрл д работает
                                                            • +6
                                                              сижу на винде, но без православных sed и grep жить не смог, скачал их для win32
                                                              а затем подтянул архив с bash'ем, включая эмулятор терминала, теперь радуюсь нормальной консоли в винде

                                                              Потом накатили xOrg, поставили kde, используете ext вместо ntfs, grub, как загрузчик, Гимп, ЛибреОфис, Firefox, MPlayer в качестве прикладного ПО. На чём вы, говорите, сидите? =)
                                                              • 0
                                                                Кстати, одно время пользовался связкой coLinux + Xming, и да — границы стирались.
                                                                • 0
                                                                  на счет kde вы угадали :)
                                                                  браузер chrome dev-m
                                                                  еще Xming есть
                                                                • 0
                                                                  Рецептом не поделитесь? Или направлением для раскопок? А то начинать гуглинг с «эмулятор терминала windows» не производительно… Слишком много вариантов, чтобы экспериментировать.
                                                            • +3
                                                              Банально расширяют кругозор. Может оказаться, что используя идеи из LISP можно более эфектно решать задачи на том же C/C++. Самый простой пример — абстрактные алгоритмы из STL и boost.
                                                              • 0
                                                                Никто не говорит что вы должны знать лисп, речь идет только о непостижимости.

                                                                Вообще, лисп достаточно простой язык и при этом очень интересный.

                                                                В универе курс лиспа очень нравился :)
                                                                • +1
                                                                  Должен признаться, одна вещи в лиспе для меня точно непостижима: затем столько скобок???
                                                                  • 0
                                                                    Прочитайте Practical Common Lisp. Мне хватило недели, чтобы освоиться с синтаксисом и привыкнуть к скобкам, а после написания первых макросов отпал вопрос о количестве скобок. Не надо бояться нового — просто читайте, пишите код, и скоро поймёте, в чём суть и сила Lisp.
                                                                • +1
                                                                  Регэкспы нужны для разбора строк средней сложности, язык программирования тут не при чем. То что на Вашей задаче не нужно работать со строками, не означает что в будущем не появится другая задача.

                                                                  Регэкспы — очень распространенная технология. Несомненно, знакомство с регэкспами отражает уровень программиста.
                                                                • +2
                                                                  Введения не хватает. А так очень даже полезно, особенно для студентов =)
                                                                  • +14
                                                                    Некоторым преподавателям тоже не помешало бы.
                                                                  • 0
                                                                    Многократные вызовы идемпотентных функций (например вызов save() по нескольку раз, «чтобы уж точно»).


                                                                    Вспоминаю и смеюсь, когда много лет назад мой друг сохранял вижуалбейсиковый проект в среде Visual Studio, несколько раз подряд нажимая Save на панели инструментов, и своего друга научил так делать. Я был удивлен.
                                                                    • +6
                                                                      Вот не знаю по поводу VS но вот MS Office приучил целое поколение по внутреннему таймеру тыкать Ctrl+s дабы не утерять плоды своего труда, что часто случается до приобретения данного рефлекса. Вероятно, отсюда же растут ноги и у повторного нажатия кнопки «Сохранить».
                                                                      • +4
                                                                        Вряд ли. Я сам на автомате постоянно нажимаю Ctrl+Shift+S, с промежутком в полторы минуты где-то, но один раз) Два раза может нажимать только параноик или человек, не совсем понимающий, «как оно работает».
                                                                        • +1
                                                                          Аээ, простите. У меня глубокая ночь. Я должен был уточнить, что все нажатия совершались в течение 10 секунд. Около 7-8 нажатий за 10 секунд перед выходом из IDE.
                                                                          • +1
                                                                            На самом деле, сработает только 1 раз, а когда клава залипает надежнее жмакнуть пар раз, так чтоб наверняка. А так я чаще встречаю людей которые не могут осилить эту комбинацию, и жалуются что у них не сохраняются файлы.
                                                                            или люди которые свято верят в то что если они закрывают программу им обязательно вылетит окошко с предложением сохранится. Причем уже более 10 раз теряли результаты, но никак не обучаются, собаки павлова думаю и то сообразительнее были
                                                                          • 0
                                                                            Вживую столкнулся однажды с такой проблемой: пользователи а) дабл-кликали по кнопкам в тулбаре (это давно было, привычка ещё с вин 3.11), причём б) делали это плохо — т.е. иногда у них получалось, а иногда выходило просто два клика подоят.
                                                                            Пришлось ставить защиту и от такого дурака — отучить их от оказалось нереально.
                                                                          • +12
                                                                            «Вы считаете само собой разумеющимся наличие скрытых переменных и не задумываясь валите любые проблемы с программой на них!»

                                                                            Если кто нибудь пояснит мне что такое «скрытые переменные» я начну валить на них все баги!
                                                                            • 0
                                                                              Возможно, подразумевался shadowing, когда одна переменная в локальной области видимости перекрывала другую с таким же именем, но на уровень (несколько уровней) выше. Могу ошибаться.
                                                                              • +9
                                                                                Судя по всему абзацу мне показалось, что «скрытые переменные» — это нечто, влияющее на Вашу программу, но не написанное в коде. Т.е. системная переменная, хранящая например фазу луны и влияющую на работу кода.
                                                                                • 0
                                                                                  Я тоже склоняюсь к варианту, который предложил <~demand>. Когда переводил еще подумывал развернуть эту мысль, но решил не трогать авторский текст.
                                                                                  • +2
                                                                                    Скорее, это понятие из физики :-)
                                                                                  • +2
                                                                                    Не каждый «Йо-Йо код» плох. Как пример из текущего проекта: парсится CSV файл, в котором содержится дамп общения device<->device. В памяти по логике работы лучше держать фреймы, в которых лежит нормальное бинарное представление сообщений. Так же некоторые фреймы могут быть отображены, в процессе отображения идет приведение массива байт к его визуализации, что является обратным действием к парсингу сообщения.

                                                                                    Если исходить из предпосылки, что Йо-Йо код плохо и его нужно однозначно выкинуть, то видится 2 решения:
                                                                                    1. в лоб: хранить как и считанную строку дампа, так и распарсенный дамп в каждом фрейме.
                                                                                    2. хранить только считанную строку дампа, но когда нужна работа по посылке или анализу приводить все к массиву байт.
                                                                                    • –1
                                                                                      Лишний раз убедился, что не зря выбрал эту профессию =)
                                                                                      • +7
                                                                                        >(ООП) Наличие огромного количества «....Manager» классов, которые содержат все методы манипуляции с объектами, которые в свою очередь совсем не содержат (или содержат мало) методов.

                                                                                        Думаю, что очень много людей не согласятся с этим. Особенно джавистов. Я предпочитаю держать модели «чистыми» и ничего плохого в этом не вижу, кроме того, что якобы это не ООП.
                                                                                        • –4
                                                                                          а вы так уверены, что вы — хороший программист?:)
                                                                                          • +2
                                                                                            А вы?
                                                                                            • +2
                                                                                              Я-то тут при чем? Это же вы пишете: «Я предпочитаю… и ничего плохого в этом не вижу». Т.е. в качестве аргумента вы приводите лишь свой авторитет.
                                                                                              • 0
                                                                                                Первое — я не увидел агрументов, почему менеджеры для управления объектами это плохо. Второе — я не приводил свой пример как единственно правильный путь («толстые модели это плохо» vs «тонкие модели это плохо»).
                                                                                            • +4
                                                                                              На самом деле helions8 прав. Тут или делать Manager-ов, которые умеют сохранять модели, и тогда это якобы не ООП. Или делать модели, которые умеют сохранять сами себя, но тогда нарушается принцип SRP, и тогда это тоже кагбе плохое ооп
                                                                                              • +1
                                                                                                Хоть вы и сказали с иронией, но оба решения действительно проблемные и вы правильно все расписали. Я пришел к выводу, что истинна где-то по средине :) Модели сохранять должен репозиторий. Manger должен реализовывать конечные сценарии. В модели — только инкапсуляция данных и некоторое базовое (я бы сказал даже аксиоматическое) поведение. Ну и для сложных случаев контекстные модели-обертки (CDI или Bounded Context из DDD).
                                                                                                • 0
                                                                                                  Полностью поддерживаю. Ни то, ни другое. Менеджеры чаще всего содержат вообще все, что только можно придумать для объекта. Верно, это должны быть разные компоненты — одни отвечают за сохранение, другие за какое-нибудь кэширование, третие — еще за что-нибудь. Менеджер может быть чисто «for convenience» — набором из нескольких наиболее используемых методов.
                                                                                            • +2
                                                                                              Вот пример, который на мой взгляд отражает суть этого утверждения:

                                                                                              class Point
                                                                                              {
                                                                                              protected $_x;
                                                                                              protected $_y;
                                                                                              }


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

                                                                                            • +1
                                                                                              (Функциональное с «чистыми»(pure) функциями) Использование копипасты из чужого кода для того чтобы побороть I/O и монады.

                                                                                              Вопрос к таким горе-программерам: нахера козе баян — нахера вообще писать на том, что не умеешь готовить? :-)
                                                                                              • +2
                                                                                                А есть еще способы научиться готовить?
                                                                                                • 0
                                                                                                  Я думаю, что подразумевалось написание кода, используемого в производстве, т. е. не для самообучения. Но даже если и для обучения, то все равно тупое использование копипасты бесполезно, все равно что зубрежка.
                                                                                              • –5
                                                                                                Очень сумбурно написано. До конца не осилил.
                                                                                                Лучше бы посоветовали прочесть «Совершенный код» макконела. Там все подробно, с доказательствами и нормальными рассуждениями.
                                                                                                • +2
                                                                                                  Значит, у вас не наболело…
                                                                                                • +28
                                                                                                  > Многократные вызовы идемпотентных функций (например вызов save() по нескольку раз, «чтобы уж точно»).

                                                                                                  цитирую из статьи про анализ исходников Google Chromium
                                                                                                  if (!file_util::Delete(db_name, false) &&
                                                                                                          !file_util::Delete(db_name, false)) {
                                                                                                      // Try to delete twice. If we can't, fail.
                                                                                                      LOG(ERROR) << "unable to delete old TopSites file";
                                                                                                      return false;
                                                                                                  }
                                                                                                  

                                                                                                  Этот код может показаться многим программистам странным. Какой смысл два раза пробовать удалить файл? А смысл есть. Тот, кто его писал, достиг просветления и суть бытия программ. Файл однозначно удаляется или не удаляется только в учебниках и абстрактном мире. В реальной системе бывает так, что файл только что нельзя было удалить и мгновением позже — можно. Причиной тому могут быть антивирусы, вирусы, системы контроля версий, и бог весть что ещё. Программисты часто не задумываются о подобных ситуациях. Они мыслят так, раз не удалость удалить файл, то значит и не получится. Но, если хочется сделать хорошо и не мусорить в каталогах, нужно учитывать эти посторонние воздействия. Я сталкивался с ровно такой же ситуацией, когда файл не удаляется один раз на 1000 запусков. И решение было ровно таким же. Ну, разве что я ещё на всякий случай Sleep(0) вставил посередине.
                                                                                                  • 0
                                                                                                    И все равно это тяп-ляп. По-хорошему нужно разобраться почему его может не получиться удалить и починить правильно.
                                                                                                    • +10
                                                                                                      > И все равно это тяп-ляп

                                                                                                      Добро пожаловать в реальный мир, Нео.

                                                                                                      > нужно разобраться почему его может не получиться удалить
                                                                                                      написано же, почему (я к списку добавил бы — если в windows — построитель превьюшек в проводнике, который лочит jpg-файлы и avi-файлы)

                                                                                                      а как бы вы поступили, кстати?
                                                                                                      • –2
                                                                                                        Может быть и также, сильно зависит от ситуации. Но как пример я бы этот код приводить не стал.
                                                                                                        • +5
                                                                                                          ну, я понимаю эту ситуацию примерно так, что:

                                                                                                          бывает много ситуаций, когда файл лочится на микросекундное время. и если делать delete один раз, то файл не будет удаляться в 30% случаев (что много), а если делать два delete, то файл останется только в 0.1% случаев (что по крайней мере приемлимо)
                                                                                                          цифры процентов я сейчас взял с потолка, но идею вроде бы описал.

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

                                                                                                          в данном случае мы знаем проблему, не готовы бросить все силы на её идеальное решение, и поэтому используем достаточно приемлимое решение. по-моему, это как минимум не нужно осуждать (а в посте осуждаются «Многократные вызовы идемпотентных функций (например вызов save() по нескольку раз, «чтобы уж точно»).»
                                                                                                          • –1
                                                                                                            Возможно этот файл читается только этой программой и только из определенного места. Но возможно из другого потока. Тогда просто ставим lock на запись и удаление, чем нормально фиксим проблему.

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

                                                                                                            И вообще кто знает как этот код возник, может оно и так бы работало, а человек просто напрасно перестраховался.

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

                                                                                                              на мой взгляд, это катит как «обозначили проблему, предложили приемлимое решение». и это кактит как опровержение тезиса из исходной статьи.
                                                                                                              • 0
                                                                                                                А вот тут пишут что залоченный файл можно переименовать и пометить чтобы его винда стерла после перезагрузки:

                                                                                                                stackoverflow.com/questions/1040/how-do-i-delete-a-file-which-is-locked-by-another-process-in-c

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


                                                                                                                  Google Chromium кроссплатформенный
                                                                                                                  • +1
                                                                                                                    В юниксах вроде как нет проблемы с блокированием файлов. Ну и есть IFDEF-ы.
                                                                                                                    • 0
                                                                                                                      ну, вот и оцените теперь время/стоимость кросс-платформенной разработки и тестирования этой фичи, со всеми ифами и ифдефами, которые срабатывать будут редко во время какой-то не самой частой операции.

                                                                                                                      • 0
                                                                                                                        Начинали с того, что пример плохой. Разобрали, предложили варианты. Понаставили мне минусов. Надо было поставить плюсик и идти дальше писать говнокод. Был неправ.
                                                                                                                        • 0
                                                                                                                          я конечно немного поздно сделал этот скриншот, но минусов я вам не ставил
                                                                                                                          clip2net.com/s/1gfjI

                                                                                                                          разобрали, предложили варианты, которые увеличат время разработки проекта раз наверное в 5 и все эти 80% нового кода будут проявляться в мелких несущественных с вероятностью 1 к 10000 ситуациях.
                                                                                                                          да, звучит разумно, сейчас поставлю напишу в саппорт гуглу попрошу их всё переделать
                                                                                                      • +1
                                                                                                        Согласен, это говнокод. Можно было хотя бы попытаться определить причину первой ошибки, и пытаться удалять второй раз после задержки. А вообще, для подобных ситуаций, есть понятия таймаута и числа повторов.
                                                                                                        • 0
                                                                                                          рискну предположить, что задержку там поставить нельзя, потому что это UI-тред.
                                                                                                          • 0
                                                                                                            :-) тем хуже для кода…
                                                                                                            • +3
                                                                                                              удаление файлов в контексте UI-треда — это экстравагантно
                                                                                                              • 0
                                                                                                                Вот-вот!
                                                                                                                • 0
                                                                                                                  Моё мнение, тезисно:
                                                                                                                  1. два delete подряд — не ошибка
                                                                                                                  2. это не идеальное решение
                                                                                                                  3. это решение — максимально полезное среди решений со схожей сложностью
                                                                                                                  4. выбирая между простым частичным решением (оно же, по мнению интернет-аналитиков, «экстравагантный» «говнокод») и увеличением сроков разработки в разы, я бы, на месте гугла, выбрал простое частичное решение и послал бы интернет-аналитиков в задницу. К сожалению, я не гугл и не могу так поступить :)
                                                                                                                  • 0
                                                                                                                    Отличный ответ! Спасибо, особенно по пункту 4.
                                                                                                                    Вынужден полностью с Вами согласиться.
                                                                                                          • +1
                                                                                                            И все равно это тяп-ляп. По-хорошему нужно разобраться почему его может не получиться удалить и починить правильно.

                                                                                                            Пф… У меня в VS 2008 проекты новые не создаются, пока их же секьюрити эссеншиалс не выключу. Мне вот инетерсно, если бы вместо ошибки «ой, не могу» в МС начали работать над хотфиксом, сколько бы времени ушло на «починить правильно»…
                                                                                                          • +5
                                                                                                            Интересный подход. Скажите, а почему вы пробуете удалять только дважды? Ведь если попробовать удалить три раза подряд, то вероятность удаления вырастет на 50%!
                                                                                                            • +1
                                                                                                              Это если удалить можно было мы максимум за 6 раз! Откуда такая уверенность, или просто число шесть нравится? :-D
                                                                                                              • +1
                                                                                                                >> Откуда такая уверенность?
                                                                                                                — Какова вероятность встретить крокодила на улице города?
                                                                                                                — 50/50: Или встречу, или нет!
                                                                                                                • –1
                                                                                                                  Если удалить можно по крайней мере один раз за сто попыток, то вероятность вовсе не 0,5, как у Вас, а совсем даже 0,01.
                                                                                                              • 0
                                                                                                                задам вам тот же вопрос, что и первому комментатору. а как бы вы поступили?
                                                                                                                • 0
                                                                                                                  >> а как бы вы поступили
                                                                                                                  Все зависит от задачи. Можно попробовать удалить заблокированный файл позже, при наступлении похожего события, т.е. удалять не конкретный файл, а сразу некоторое множество, в которое попадет и текущий файл, и все неудачные предыдущие попытки. Можно n раз пытаться удалять файл через определенное время, например, через каждые 0,1мсек (предложенный выще вариант — частный случай с n = 2 и 0сек). Можно аналогичного события не ждать, а подписаться на события файловой системы, и удалять файл по освобождению. Можно удалять при закрытии программы. Можно при следующем запуске. Вобщем, вариантов масса.
                                                                                                                  • 0
                                                                                                                    насколько я знаю, нет события «файл разлочен». про первый вариант с паузой я написал чуть выше.
                                                                                                                    третий и четвёртый — да, хорошие варианты. я бы скомбинировал их с delete&&delete
                                                                                                                  • 0
                                                                                                                    Если так уж нужно удалить файл, то логично делать это не два раза подряд в коде (как тут заметили, возникает вопрос, а почему два раза, а не три или не тридцать три), а в цикле, пока не удалится или пока операция не будет отменена.
                                                                                                                    • 0
                                                                                                                      а в цикле, пока у пользователя не кончится терпение смотреть на белый не реагирующий на нажатия экран браузера и он не прибьёт процесс таскменеджером.

                                                                                                                      нет, так тоже нельзя.
                                                                                                                      • 0
                                                                                                                        Я поэтому и написал: " или пока операция не будет отменена". IO операции в UI треде, разумеется, делать не стоит.
                                                                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                                          • –1
                                                                                                                            Моё мнение, тезисно:
                                                                                                                            1. два delete подряд — не ошибка
                                                                                                                            2. это не идеальное решение
                                                                                                                            3. это решение — максимально полезное среди решений со схожей сложностью
                                                                                                                            4. выбирая между простым частичным решением (оно же, по мнению интернет-аналитиков, «экстравагантный» «говнокод») и увеличением сроков разработки в разы, я бы, на месте гугла, выбрал простое частичное решение и послал бы интернет-аналитиков в задницу. К сожалению, я не гугл и не могу так поступить :)
                                                                                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                                  • +1
                                                                                                                    Удаление файла — идемпотентная операция? Ну, у меня для вас плохие новости.
                                                                                                                    А кроме того, так можно удалить чужой файл, например.
                                                                                                                  • +11
                                                                                                                    Вопрос к переводчику: «Вам послайсить или целым писом?»
                                                                                                                    • 0
                                                                                                                      Отличная статья и, в кои-то веки, близкий к отличному перевод! Спасибо.
                                                                                                                      • –16
                                                                                                                        не заметил ни каких пометок в начале и конце текста что это перевод и ссылку на источник. Плагиат?
                                                                                                                        • +3
                                                                                                                          Рядом с заголовком иконка z>я, в футере ссылка на оригинал и автора (cwenham).
                                                                                                                          • –12
                                                                                                                            как тут (на хабре) всё сложно…
                                                                                                                            нет бы написать текстом, зачем такой выпендрёж нужен…
                                                                                                                            • +1
                                                                                                                              Нет бы разобраться в терминологии и основных концепциях Хабра, перед тем как беспочвенно обвинять людей в плагиате.
                                                                                                                              • –5
                                                                                                                                мозги где? там значок вопроса не видно, да?
                                                                                                                                • 0
                                                                                                                                  да заткнитесь уже
                                                                                                                          • +7
                                                                                                                            image
                                                                                                                            image
                                                                                                                            • –10
                                                                                                                              какая досада, почтовик картинки не кажет, пришлось сайт открывать.
                                                                                                                            • +1
                                                                                                                              (блин, в каждой статье про перевод это)

                                                                                                                              И в начале, и в конце текста есть пометки, в начале — Z->A, в конце — ссылка на автора, рядом с ником автора перевода.
                                                                                                                              • –5
                                                                                                                                а мне видимо надо было от рождения это знать, чтож поделать, родители не доработали, нужную программу не до грузили в мозг :)
                                                                                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                                                  • –2
                                                                                                                                    разве? по моему я подъёбывал, не всем же дано целую библиотеку в голове с рождения иметь :)
                                                                                                                            • –1
                                                                                                                              Да на троечку перевод, если честно.
                                                                                                                            • –2
                                                                                                                              Указатели, рекурсии — может стоит переименовать статью «Признаки плохого С++ программиста»? В том же php указатели в большинстве случаев не нужны, и даже вредны, так как усложняют понимание программы не принося ощутимой пользы, или в силу заморочек интерпретатора создают труднонаходимые баги. А рекурсии опасны и их часто лучше заменить более сложным итеративным алгоритмом, одна рекурсия при неосторожной работе с памятью съест всю память на сервере что положит сайт и кучу бэкграунда, проц тоже может весь скушать, да можно писать без утечек памяти, но программ без багов не бывает и рекурсия может проявить себя только в условиях которые не были предусмотрены при написании. С итеративным алгоритмом вероятность такого меньше.

                                                                                                                              Lisp, тезис Чёрча-Тьюринга — вы серьезно, без этого нельзя быть хорошим программистом?

                                                                                                                              Регулярные выражения — тоже спорно, гуру в регулярках может быть плохим архитектором, обратное тоже верно.

                                                                                                                              • 0
                                                                                                                                без способности без проблем понять эти вещи — да, нельзя быть хорошим программистом. да и вообще, хороший программист должен знать всю область — по крайней мере на неплохом, но чуть поверхностном уровне и быть специалистом в своей подобласти
                                                                                                                                • –2
                                                                                                                                  Ну тезис Чёрча-Тьюринга при необходимости понять можно, вопрос только нужно ли. Но если вы это используете как тест а не как обязательный набор знаний то ок, пусть будет, хотя и тест сомнительный.

                                                                                                                                  Но Lisp (а так же prolog) это языки требующие своего особого мышления. Сам лично сталкивался, люди только начинающие изучать программирование, с «чистым мозгом» осваивали lisp лучше и быстрее людей у которых уже был небольшой опыт в программировании на языках типа С++, php, pascal и пр. Но это не сдалало их как ни странно хорошими программистами. Мне чтобы понять lisp преходилось «вывернуть» мозг привычный к алгоритмическим языкам (назовем их так, не могу подобрать другого слова). Расширения кругозора имеет не только плюсы но и свои минусы, используя подходы lisp в php (для примера) можно так извратить код, что другому программисту будет крайне сложно с ним работать. А теперь представьте что над проектом параллельно работают 10 программистов и каждый со своим вот таким расширенным кругозором в какую нибудь сторону (а у кому-то из них и брейнфак в качестве хобби нравится). Через сколько времени команда разругается а проект превратится в полный шлак? Так что всего в меру и очень осторожно. Вот только как я уже писал вырабатывается определенный стиль мышления, и понять когда можно применять неродные для языка подходы а когда нельзя, наверное будет очень сложно самостоятельно.

                                                                                                                                  А по поводу всей области: В мире сотни, если не тысячи языков программирования, что стоит изучить их все? Я считаю что только основные, которые могут быть как то связаны с выбранной для специализации областью. Я не спорю что С++, Java полезно знать на минимальном или среднем уровне, но Lisp имеет свою узкую нишу, и вряд ли достаточно (чтобы оправдать потраченное на него время) можно из него вынести например в веб-программирование. Может лучше уделить время оттачиванию знаний в своей подобласти чем разбрасыватся по всей области для расширения кругозора?

                                                                                                                                  И еще, поверхностное знание это всего лишь ступень к знанию, к пониманию если угодно, само по себе оно ничего не стоит, так как не закреплено опытом а значит не может принести какую-нибудь идею в другую область (увы, так работает мозг) и не позволяет работать в своей. Чтобы хоть как-то «знать» язык нужно хотя бы пару месяцев на нем пописать на реальном проекте, а это уже не поверхностное знание.
                                                                                                                                  • 0
                                                                                                                                    Lisp — дедушка современных динамически-типизированных языков. Учитывая что почти все современные языки движутся (обратно?) в сторону различных функциональных возможностей, а lisp в значительной мере функциональный язык, то знать его «трюки» нужно для того чтобы хорошо писать на этих языках, кмк. По большому счету, в ruby, python, [вставьте свой любимый динамический язык] от лиспа отличается система типов, стандартные библиотеки и синтаксис (пробелы, скобочки — какая разница?). А приёмы всё те же.
                                                                                                                                • +8
                                                                                                                                  По поводу рекурсии, кстати.

                                                                                                                                  /*
                                                                                                                                  «Итерация свойственна человеку, рекурсия божественна». Л. Питер Дойч
                                                                                                                                  Видно, у бога стек длинный. А мы останемся людьми.
                                                                                                                                  */

                                                                                                                                  for( int i = 0; i < depth; i++ ) {

                                                                                                                                  }

                                                                                                                                  © ithappens.ru/story/7508
                                                                                                                                  • +3
                                                                                                                                    Видно, у бога стек длинный.


                                                                                                                                    Видно комментатор кода несилен в языках, и не знает, что хвостовой рекурсии (Tail call optimization) сто лет в обед, и никакого стека, блджад.
                                                                                                                                    • 0
                                                                                                                                      1977 год, между прочим, Guy Steele. Вот вам и польза от знания Lisp'а налицо, что называется, а вы говорите СкрипачLisp не нужен. Рекурсия божественна, воистину!
                                                                                                                                      • 0
                                                                                                                                        Из википедии (да знаю что она не всегда соответствует истине, если где неправда поправте):
                                                                                                                                        «Хвостовая рекурсия — специальный случай рекурсии, при котором рекурсивный вызов функцией самой себя является её последней операцией.[1] Подобный вид рекурсии примечателен тем, что может быть легко заменён на итерацию, что реализовано во многих оптимизирующих компиляторах.»,
                                                                                                                                        «Создатели функционального языка Scheme, одного из диалектов Lisp, оценили важность хвостовой рекурсии настолько, что в спецификации языка предписали каждому транслятору этого языка в обязательном порядке реализовывать оптимизацию хвостовой рекурсии.» — Ну и смысл огород городить если все равно все сводится к итерации? Где практическая польза этого вида рекурсии (ну за исключением языков где это одна из основ)?
                                                                                                                                        • +3
                                                                                                                                          Вы не понимаете принципа функционального программирования, как программирования без побочных эффектов в идеале (Haskell, например, или Scheme). Итерация в C и C-подобных языках императивна, имеет побочные эффекты в форме изменения переменной-счетчика, например.

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