четверг, 15 сентября 2011 г.

[prog.thoughts] Продолжение темы о глупости применительно к программированию

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

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

Теперь к основной теме. Когда я был молодым, самоуверенным и шибко умным, я сделал для себя вывод о том, что баги в программах, в основном, определяются тремя основными причинами:

  1. Непониманием. Например, разработчик недопонял условия задачи и не реализовал обработку каких-то граничных случаев, поскольку посчитал, что их не будет в принципе. Скажем, в тестовом задании, которое я практиковал, одна из проблем была в том, что разработчик не понимал, что лицензионная информация может быть где угодно в файле, а не только в начале. Из-за чего программа была обречена в ряде случаев работать неправильно.
  2. Незнанием. Например, разработчик не знал о каких-то специфических особенностях той или иной функции (или предметной области вообще). Скажем, функция возвращает char* динамически выделенный блок памяти и этот блок отдается во владение программисту, который затем должен его сам освободить. Если программист об этом не знает, то произойдет утечка памяти.
  3. Небрежностью/невнимательностью. Типичная C/C++ная ошибка – написание в if-е присваивания вместо равенства. Такие ошибки могут вызываться целым рядом факторов – от врожденной безалаберности разработчика, до авральных условий работы под давлением со стороны начальства/клиента.

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

Я думаю, что ни одна из перечисленных выше причин не содержит достаточного пространства для глупости. Причем если в причинах #2 и #3 такого простора нет изначально, то вот с #1 ситуация интереснее.

То, что конкретный человек может неверно (очень неверно) истолковать даже, казалось бы, очень подробные условия задачи – это нормально. Часто, к сожалению, встречается. Но признаком глупости служить не может.

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

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

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

Добавлю еще один фактор – программирование требует от человека двух совершенно противоположных качеств. Ты должен решать сложные задачи и, как следствие, получать удовольствие от факта нахождения решения. Но тут же ты должен подвергнуть найденное решение (т.е. свое детище) разгромной критике, чтобы проверить его качество и найти недостатки. Такая борьба между “вот это мне уже нравится” и “это фигня какая-то”, имхо, так же не проходит бесследно.

Вышесказанным я хотел сказать, что в программировании достаточно объективных сложностей, чтобы совершать большое количество ошибок, в том числе и “глупых”. Что вовсе не является следствием глупых решений – т.е. без обдумывания или с доминированием иррациональных доводов. Так что глупости в программировании не так уже и много. Хотя встречается.

Сразу вспоминаются такие случаи, которые кроме как глупостью объяснить не получается. Спрашиваешь у человека: “Ты сделал вот это?” -- “Да, сделал!” Берешь его код из репозитория, а он даже не компилируется, поскольку содержит синтаксические(!) ошибки. Исходя из каких соображений человек говорил, что у него все сделано и работает, я не представляю.

Еще одно проявление – стремление старое выбросить и переписать все заново. Когда это хочет сделать молодой разработчик – это еще объясняется недостатком опыта. Но когда опытный… Тут либо глупость, либо же крайняя степень безысходности (у меня однажды такое было, когда окончательно задолбавшись вычищать чужое дерьмо чужие баги я всерьез предлагал написать с нуля новый, чистовой вариант).

Ну и еще одно проявление, опять же достаточно часто встречающееся и испытанное на собственной шкуре. Это языковой фанатизм. Например, слепая вера в то, что C++ – это язык на все случаи жизни. Или что кроме Java ничего и не нужно. Или что достаточно взять Erlang или Haskell и ваши волосы станут мягкими и шелковистыми программы будут содержать намного меньше проблем. К счастью, с возрастом это проходит :)

А одним из самых тяжелых проявлений глупости в программировании я бы назвал стадию “Я все видел, я все знаю”, до которой я сам доходил неоднократно доходят некоторые опытные разработчики. После чего перестают учиться и с трудом воспринимают новое. А новое в программировании все-таки появляется постоянно, хоть и не так часто, как это кажется молодым хакерам. Можете мне поверить – я видел, я знаю! ;)

2 комментария:

имя комментирует...

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

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

(и на самом деле тут ситуация, обратная обычным "не проверил граничные условия" -- тут как раз "проверил только граничные, и забыл про основные")

пп.2 и 3 по-моему вообще недостатки языка и/или компилятора, т.к. обработка такой инфы должна происходить автоматизированно, а не в голове у разраба; опять же "не содержит синтаксические ошибки" по идее должно быть флажком и проверяться автоматически при его присвоении

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

eao197 комментирует...

>пп.2 и 3 по-моему вообще недостатки языка и/или компилятора, т.к. обработка такой инфы должна происходить автоматизированно, а не в голове у разраба

Это вряд ли возможно полностью. Помню, как при программировании расчетов мы умудрялись знаки операций путать (минус заменяли на плюс) или вместо PI/2 писали просто PI. Из-за элементарной невнимательности.