пятница, 26 декабря 2008 г.

Why FP doesn't matter yet? ;)

В последнее время в определенных кругах наблюдается повышенный шум по поводу функционального программирования (ФП). В одном из обсуждений ФП подкинули ссылку на статью Why Functional Programming Matters. Меня, как завзятого скептика по отношению к ФП статья не впечатлила. Уж сильно обсуждаемые там примеры далеки от того, чем мне приходится заниматься. Но, в попытке разобраться с примерами кода из статьи я хорошо понял, почему ФП, не смотря на свой почтенный возраст, до сих пор широко не распространено. А вот почему:
easydiff f x h = (f(x+h)-f x) / h

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

easydiff(f, x, h) = (f(x+h)-f(x))/h

Глядишь, и народ бы к ним потянулся :)

четверг, 25 декабря 2008 г.

Программистам нужны простые решения?

В своем интервью Don Syme (главный разработчик языка программирования F#) сказал, что сейчас программистам нужны простые решения:

People thirst for simplicity. People need simple solutions to the problems that really matter: data access, code development, deployment, cloud computing, Web programming, and parallel programming, to name a few.

Будучи сам программистом, я не могу согласиться с таким утверждением. Мне не нужны простые решения. Простое решение, это, например, язык Oberon. Ну и где он, кто им пользуется? Даже Java и C#, которые начинались как гораздо более простые инструменты, чем C++, сейчас по сложности или приближаются к нему, или уже превзошли (в частности, C# 3.0 и готовящийся к выходу C# 4.0). Программистам нужны мощные решения. А мощность и простота редко идут рядом. Что действительно нужно, на мой взгляд, так это многослойное решение, которое можно изучать и применять, постепенно переходя от простого к сложному, как бы снимая слой за слоем. При этом обеспечивается легкое и быстрое получение первых результатов. По сути, человек быстро и незаметно подсаживается на иглу. После чего он вынужден либо изучать инструмент более тщательно, либо менять инструмент. Для достижения такой многослойности, как мне кажется, нужно придерживаться нескольких правил (все нижеследующее относится к инструментам, которые действительно делают что-то полезное): 1. Решение (инструмент) должно быть построено на основе небольшого количества простых идей и понятий. Например, SObjectizer в своей основе имеет только агентов с их состояниями, сообщениями и событиями. Все остальное, это надстройка над ними. 2. Решение (инструмент) должно быть снабжено хорошими обучающими материалами и документацией. Понятие "хороший", конечно же, субъективно. Но, например, изучать Ruby по книге "Programming Ruby" гораздо проще, чем C++ по книге "The C++ Programming Language". А все из-за того, насколько по-разному в каждой из книг построена подача материала – в одной идет плавное погружение человека в новый для него язык, а во второй – практически мгновенный переход к деталям. Поэтому что-то вроде Tutorial или Developer Guide с последовательным изложением тем от простого к сложному, это must have. При несомненной важности подобного обучающего руководства обязательно должно быть что-то вроде полного описания всех его классов, функций и пр. -- подробный Reference Manual. Поскольку очень обидно, когда после прочтения Tutorial-а пытаешься сделать что-то свое и негде найти список параметров какого-то метода. 3. Инструмент, если речь идет о более-менее серьезной библиотеке, должен иметь API нескольких уровней. Верхний уровень позволяет очень просто выполнять наиболее общие или наиболее востребованные действия. На этом уровне широко используются умолчания и пользователь, как правило, не имеет возможности делать какие-то тонкие настройки. Например, если какая-то операция полагается на использование пула потоков (thread pool), то пользователь не может указать какой именно пул потоков должен использоваться, сколько в этом пуле должно быть потоков, с каким приоритетом они должны работать и пр. Как раз такой верхний уровень API призван обеспечить легкое получение первых результатов у новых пользователей. Хороший пример – это параметры таких шаблонов, как std::vector, которые имеют значения по умолчанию. Вот, скажем, есть у std::vector такой параметр, как Allocator. А подавляющему большинству C++ программистов никогда не приходится его определять самостоятельно. Под верхним уровнем должно быть несколько более низких уровней, каждый из которых требует от программиста все лучшего и лучшего знания инструмента и понимания того, чего же программист хочет достичь. Но при этом программисту предоставляется все больше и больше возможностей. Ярким нарушением этого принципа, мне кажется, является библиотека Poco. В ней, к примеру, есть классы ActiveMethod и ActiveResult, которые используются для реализации фьючерсов. Но указать ActiveMethod, на каком именно пуле потоков должен выполняться асинхронный вызов метода нельзя. 4. Решение (инструмент) должно быть снабжено большим количеством примеров разнообразных способов его использования. Качественных примеров. Ведь зачастую фрагмент из примера посредством copy-and-paste переносится в код пользователя. Или же пример используется в качестве "рыбы" для программы пользователя. Обидно, когда библиотека содержит только примеры вида "Hello, world", либо не содержит примеров вовсе – в качестве таких примеров пытаются выдать unit-тесты. Хотя, например, в случае с ACE распространяемые с ACE тесты довольно часто оказываются вполне хорошими примерами и серьезно помогают во время изучения очередной возможности ACE. Но это, скорее, исключение. Не так уж и мало всего перечислил. Что, на мой взгляд, еще раз подчеркивает одно житейское наблюдение – не бывает простых решений сложных проблем. И для того, чтобы сделать что-то, что создает впечатление простого, нужно приложить немало усилий. Как замечательно сказал Алан Перлис:
Simplicity does not precede complexity, but follows it.
(источник).

среда, 24 декабря 2008 г.

Профессиональные убийцы времени

В программировании многое очень быстро меняется. Поэтому нужно стараться держать нос по ветру и отслеживать свежие течения. Но, в ряде случаев этот процесс отнимает гораздо больше времени, чем хотелось бы. В последнее время меня раздражают две вещи, речь о которых пойдет ниже. Во-первых, это RSS-ленты. В самом RSS, как в инструменте, ничего плохого нет. Плохо, что среди потока новостей находится много "информационного мусора". На одно действительно хорошее и ценное сообщение (чаще всего это анонсы каких-то инструментов, реже ссылки на полноценные статьи) приходятся десятки ссылок на чьи-то блоги с еще одним мнением на какой-то фундаментальный вопрос. Особенно часто сейчас это наблюдается на тему Concurrent и Parallel Programming. Какой-нибудь очередной Вася Пупкин открывает для себя Erlang, Actor Model или OpenMP и тут же строчит опус (благо, если короткий) в свой блог. После чего ссылка на сие творение распространяется через RSS-ленты. А я трачу 5-10 минут времени только для того, чтобы понять, что ничего нового здесь для себя не открою. Еще одна вариация убийства времени за счет RSS-лент, это когда в течение короткого времени на каком-нибудь достойном сайте появляется куча статей и статеек, рассказывающих об одном и том же, но разными словами (в лучшем случае). Так, недавно в Dr.Dobb's появилось штук пять или даже больше статеек на тему Intel Threading Building Blocks. Хотя, на мой взгляд, вполне хватило бы и одной-двух, но чуть более полных. Во-вторых, хотелось бы к профессиональным (в смысле имеющим отношение к профессии программиста) убийцам времени причислить видеоматериалы, которые все больше и больше используются для распространения информации о новых продуктах и технологиях. У Microsoft-а есть Channel9, где периодически появляются интервью с разработчиками новых продуктов и презентации этих продуктов. На Google Video часто выкладывают различные подобные материалы. После проведения различных конференций доклады скорее появляются в виде видеозаписи выступлений докладчиков, чем в виде слайдов или стенограмм. Для меня все эти видеоматериалы плохи тем, что они слишком длинные. И еще хорошо, когда рассказ сопровождается демонстрацией кода и результатов его исполнения/отладки (в свое время меня поразило, насколько информативными бывают небольшие по размеру screencast-ы с демонстрацией возможностей Ruby-On-Rails или редактора TextMate). Но когда речь докладчика всего лишь сопровождает некоторой несущественной информацией то, что демонстрируется на слайдах того же докладчика, то становится обидно за потерянное время - тот же самый объем информации можно было бы получить, потратив десять минут на чтение стенограммы доклада, чем за час просмотра этого же доклада. Мне кажется, что оба эти убийцы времени происходят от одного и того же - от халтурного отношения и от спешки. Выступает кто-то в Channel9 у Microsoft, зачем делать стенограмму его выступления? Достаточно просто опубликовать запись. Появилась где-то очередная заметка о том, насколько, оказывается, хорош асинхронный обмен сообщениями - в RSS-ленту его. Вне зависимости от того, стоит эта заметка вообще чьего-либо внимания или нет. Быстрей, быстрей, думать некогда! Нужно быстрее новую порцию интеллектуальной жвачки пропихнуть, пока пипл хавает.

понедельник, 22 декабря 2008 г.

Так ли хорошо использование мейстрим языков программирования?

Больше десяти лет я программировал на самом мейнстримовом языке программирования последних двадцати лет - C++. И не сильно задумывался, хорошо это или плохо. Однако, по большому счету, мейнстримовым программистом я все-таки не был, т.к. изрядное количество времени я работал на экзотических платформах (например, OS/2 или OS-9000), и занимался не самыми типичными задачами (АСУ ТП, работа со SmartCard-ами через PC/SC ридеры, поддержка телекоммуникационных протоколов вроде SMPP и EMI). Познакомившись за последние несколько лет с целым рядом языков, которые не являются мейнстримом (например, D, Scala, Eiffel, Nice, Erlang, Ruby, OCaml), я стал более критично рассматривать полезность следования мейнстриму. В частности, на примере языков программирования.

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

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

Для компании использование мейнстримовых платформ хорошо тем, что, во-первых, нет проблем с наймом программистов: раз это мейнстрим, значит, есть достаточное количество людей, владеющей этой платформой. Во-вторых, нет проблем ни с инструментарием, ни с документацией, ни с техподдержкой. Для мейнстрим платформ существует большой выбор самых разных инструментов (компиляторов, профайлеров, IDE, библиотек и пр.). Огромное количество книг и on-line ресурсов, даже специальных обучающих курсов. Очень большое сообщество, в котором, при желании и настойчивости можно найти ответ на любой вопрос. В-третьих, мейнстрим либо означает возможность работать на большом количестве платформ (как пример кросс-платформенность Java), либо же работать на большом количестве компьютеров (как пример распространенность OS Windows, под управлением которой работает больше 95% всех персональных компьютеров в мире).

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

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

Теперь о том, какие риски есть у мейнстрима.

В первую очередь рассмотрим риски для компании.

Начать можно с того, что существует мнение о том, что каждые 10 лет появляется новый доминирующий язык программирования. Вроде того, что с 1986-го по 1996 -- это был C++, затем с 1996 по 2006 -- Java, с 2006 -- таковым MS хочет сделать C#. Так же меняются "горячие штучки" в самой индустрии. В 70-ые годы -- мейнфреймы. В 80-е -- развитие персоналок в одной нише и сетевых ОС (в первую очередь Unix-ов) в другой. С 1990-го по 2000-й было развитие desktop-систем (как раз в это время Windows стала доминирующей ОС). С конца 90-х до недавнего времени -- WWW, Web-системы и Web-программирование. Так же где-то с 2000-го активно развиваются ниши встраиваемых систем и мобильных систем (проще говоря, программирование для мобильников).

Так вот фокус в том, что какой-то новый язык/платформа не столько отвоевывает место под солнцем у уже существующих языков/платформ, сколько создает свои ниши. Так, на C++ никто не переписывал ПО мейнфреймов, а так же C++ не вытеснил полностью C из ниши системного программирования, зато на C++ была написана целая куча desktop-ного и middleware- (типа серверов баз данных) софта. Опять же Java не смогла вытеснить C++ из этой ниши.

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

Так же это означает, что если компания собирается выходить на рынок с новым продуктом, то правильный выбор будующего технологического лидера очень важен. Не очень разумно было вкладываться полностью в Java в 96-99-ых годах. Не очень разумно было вкладываться в C++ в 2004-2008-ых годах. Но, если с перспективной технологией угодать и начать ее использовать за пару лет до ее выхода в мейнстрим, то за счет этого можно получить чисто технические преимущества. Ведь каждая новая технология устраняет часть проблем, которая присутствовала у предшественников. Скажем, C++ добавил к C поддержку ООП. Java добавила к C++ безопасность, сборку мусора и дешевую кроссплатформенность. C# добавил к Java родную поддержку Windows и элементов функционального программирования. Т.е. переходя на новые языки/платформы, разработчики получают конкурентное преимущество перед теми, кто использует "старые" технологии.

Вот, например, сейчас стало модно обсуждать multicore процессоры. Оказывается, что очень сложно добится серьезного увеличения производительности программы при переходе на 2-х, 4-х и более ядерные процессоры. Часто наблюдается даже обратный эффект, на нескольких ядрах программа работает даже медленнее, чем на одном. Во многом в этом виноваты существующие подходы к разработке программ и существующие мейнстримовые языки программирования в частности. Появление новых языков, более приспособленных к параллельному программированию, или же встраивание специальных возможностей в существующие языки сможет дать серьезное преимущество при разработке хорошо масштабируемых программ.

Еще один аспект мейнстрима для компаний. Как известно, самое важное слагаемое успеха это люди. Несколько "правильных" людей способны производить больше качественного кода, чем несколько десятков(!) "неправильных" (по наблюдениям ДеМарко и Листера, да и не только их, разница в производительности между хорошими и плохими программистами может составлять до 10 раз). Но "правильных" людей, т.е. талантливых, увлеченных программистов, зачастую интересует то, что находится "на грани", что еще не попало в мейнстрим. Многие из них хотят применять то, что они считают перспективным и интересным. Поэтому, если дать им такую возможность, то это забавным образом повлияет на возможность найма людей: предложений на рынке будет гораздо меньше, зато качество предложений будет гораздо лучше.

Т.о. мейнстрим для компании это, с одной стороны, риск упустить шанс стать лидером при смене ориентации рынка. С другой стороны, не-мейнстрим это шанс получения преимуществ за счет новых технологий, но и риск проигрыша в случае "не выстрела" этих самых технологий.

Чем же плох для разработчика мейнстрим?

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

Так же программисту нужно узнавать что-то новое и, желательно, не только в том, чем он занят на работе. Зашоренность всегда плоха. Тем более, что в программировании есть несколько совершенно разных ниш, каждая из которых требует своего инструмента. Например, для каких-то мелких, одноразовых задач хорошо подойдут скриптовые языки (типа Python или Ruby). Для desktop-приложений -- C++ (особенно для мелких, легких программ), C# и, отчасти, Java. Для server-side -- Java, C# и динамические языки вроде Erlang, Python, PHP и Ruby. Для встраиваемого ПО -- C, C++, Java, Ada. Для высоконадежного ПО с высокими требованиями к ресурсам и производительности -- C++, Ada, Eiffel. И т.д. Получается, что чем большим количеством хороших инструментов владеет программист, тем проще ему будет выбрать подходящий инструмент для какой-то из своих задач (если, конечно, у программиста есть выбор).

Sic transit gloria mundi :)

Вот и достигнута широкая известность в узких кругах! ;) После четырех лет активного участия в RSDN-овских баталиях меня сочли достойным кандидатом на включение в очередной вариант RSDN-новского гимна (я там в качестве персонажа E). Пустячок, а приятно ;) Ну и если уж хвастаться, то на данный момент я нахожусь на шестом месте в общем Top-100 всего RSDN, и на первых местах в форумах Философия программирования, C/C++ прикладные вопросы и Языки с динамической типизацией (за счет статьи о языке Ruby). Жалко только, что этот рейтинг на хлеб вместо масла не намазывается :)