01 November 2011

Замес о программировании

Краткое содержание: Delphi must die, говнокодинг как признак приближающегося конца света в следующем году, Python -- давай сделаем это по-быстрому!

Ррррр!

Есть у меня такая добрая ежегодная традиция -- писать пост скорби о Delphi (вот, к примеру, прошлогодний). 


#1. Ручное управление памятью -- чума XXI века. 
Языки без GC или хотя бы RAII давно пора отправить на заслуженный отдых. 
В упор не понимаю людей, которые после богатого плюсового опыта дауншифтятся обратно на си. 
И еще. Кэп утверждает, что вводить исключения в язык без GC/RAII может только человек с крайне специфическим чувством юмора. Try. Finally.

#2. В отсутствии нормального управления памятью все время тянет на какие-то извращения. 

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

Другой пример -- AnsiString как универсальный контейнер переменного размера для абсолютно любых целей. С контейнерами в Delphi вообще беда страшная, и мне очень хочется посмотреть в глаза человеку, придумавшего т.н. "динамические массивы" для которых нет самых тривиальных операций, вроде find() или add(). Поэтому нет ничего удивительного, что строки, которые растут динамически и для которых работает подсчет ссылок, используются как vector<byte>. Если бы еще не эта долбанутая индексация с единицы... Но, в конечном счете, за все приходится платить. Посмотрел краем глаза на возможности миграции на что-то посвежее, и понял, что сил на это придется потратить немерено, в первую очередь как раз из-за строк, которые все после полуночи превратились в тыкву строки уникодовые, со всеми вытекающими из этого последствиями для vector<byte> сценариев. 
Кстати, такой апгрейд языка для строк очень сильно похож на то, что сделали в Python3k (подробнее об этом внезапно ниже) 

#3. Убивает многословие. 
И ладно еще отсутствие в языке шаблонов (отсюда копи-паст плюс приведение типов в runtime) или крайне неповоротливо подсказывающая IDE... Я говорю обо всех этих тысячах бессодержательных символов, которые приходится тратить на var секции, на begin и end, на названия типов вроде boolean вместо bool или integer вместо int, на отсутствие операторов типа +=, отсутствие тернарного оператора, then в конструкции if, слова procedure и function... В общем, тысячи их! Пальцы программист на Delphi набегают за день в два-три раза больше символов, чем пальцы плюсового программиста. Какой-то бесконечный словесный понос, ну правда! (Справедливости ради, плюсам можно припомнить копи-пасту в .h/.cpp)

Никогда не говори никогда

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

Да, конечно, мы живем в сверхдинамичный век, век веб-приложений и скриптовых языков, которые используются для их разработки. В этих языках многое отдано в угоду максимально быстрого написания кода; никаких валидаций или проверок перед тем, как начинать его исполнять, делать не нужно -- все ошибки ты ловишь уже в runtime. Ты, или твой счастливый пользователь. 
Это совершенно классический кейс на рынке -- на определенном этапе выбросить в корзину весь написанный на PHP существующий код веб-проекта, и полностью все переписать с нуля. Конечно же, снова на PHP. 
Некоторые, причем довольно серьезные проекты, проходили этот путь по несколько раз. 

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

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

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

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

Даже самого хорошего программиста можно легко "сжечь", посадив на сопровождение плохо написанного проекта.


Хреново написанный код -- бич нашего времени. Написание программ это вечная гонка быстрей, быстрей; вечно горящие сроки, страшные дедлайны и нескончаемые компромиссы, компромиссы, компромиссы. В таких условиях менеджеры мало думают о том, кто, когда и с помощью какой матери будет сопровождать проект, который ему кровь из носу надо было сдать заказчику еще вчера. Говнокодинг, пофигизм, отсутствие какого бы то ни было code review и качество, которое решается только на уровне отдела тестирования -- стиль жизни для подавляющего большинства организаций, создающих программы.
Лично меня эта картина несказанно удручает.

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

Срезая углы

Посмотрел занятное выступление Гвидо ван Россума об истории языка Python.
Про себя отметил следующее.



#1. Добавление unicode в 2.x версию это был очевидный fail, который пришлось насильно править в Python3k. Гвидо говорит, что на момент добавления, никто толком не представлял себе что такое уникод строки и как их едят. Это в начале 2000-х. Не смешно.

#2. Python и лямбда (смайлик). В очередной раз Гвидо пересказал это забавную историю, когда на раннем этапе существования "питона" какой-то чувак прислал ему мыло: эй! ты создал классный язык, но в нем сильно не хватает lambda, map, reduce и filter!
Гвидо: что такое lambda, map, reduce и filter?
Чувак: держи патч, оно все тута!
Патч оказался полностью рабочим и было бы странным его не добавить, хотя Гвидо говорит о том, что лябды это сахар, потому что определение рядом с вызовом локальной функции, в принципе, от лямбды слабо отличается.
Потом началась бесконечная история о том, что лямбды в питоне отстой, потому что в них ни хрена нельзя сделать, и Гвидо так устал от этих наездов, что собирался на полном серьезе в 3k вообще от них отказаться.
Слава б-гу, они все-таки выжили.

#3. Код с использованием reduce всегда выглядит мутным и его пишут граждане, которые хотят козырнуть своей крутостью перед коллегами. Лично Гвидо всегда такой код переписывает на простой for и не выебывается.
LISP никак не повлиял на Python.

#4. Динамическая типизация в питоне есть следствие политики "срезания углов". Математика, связанная с выведением типов слишком сложна и приводит Гвидо в уныние.

#5. Давно не смотрел в сторону PyPy, а он сильно изменился и возмужал. Эх, найти бы время -- пощупать.

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

На этом все. Не говнокодьте!


No comments:

Post a Comment