воскресенье, июня 24, 2007

Первый в мире язык программирования

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




[Если быть совсем точным, то уж по настоящему первым языком программирования была, по всей видимости, та нотация, с помощью которой были написаны программы Чарльза Бэббиджа в знаменитой статье Ады Августы Байрон, графини Лавлейс "Sketch Of the Analytical Engine"(статья представляла собой перевод статьи итальянца Менабреа о работе разностной машины Бэббиджа и, содержала существенное дополнение, написанное самой Адой Августой). Однако это был не вполне язык программирования, да и машина, для которой он предназначался существовала только в уме гениального человека. Замечу кстати, что в 1991 году музей науки в Лондоне создал по чертежам Бэббиджа его машину и она сейчас существует в рабочем состоянии]

Итак, первый язык программирования. Это был вовсе не Фортран, а язык с удивительным названием - Plankalkül, то есть в переводе с немецкого "Исчисление планов" или "План вычислений", был разработан немецким учёным, изобретателем и конструктором Конрадом Цузе в нацистской Германии между 1942 и 1945 годами.

[Цузе также сконструировал несколько различных моделей компьютеров. Например его Z3 тоже был создан раньше знаменитых Marc I и ENIAC и являлся при этом вполне полноценной машиной. ]

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

Создание языка программирования было естественным продолжением работ по созданию "железной" части компьютеров. Сам Цузе пытался с его помощью писать программу для игры в шахматы. Работы над языком были закончены около 1946 года, однако развития язык не получил и даже написанное руководство увидело свет только в 1972 году. Из-за этого язык оказался неизвестным и существенного влияния на дальнейшее развитие индустрии не оказал (в сравнении например с тем же Фортраном).

Тем не менее Plankalkül несомненно был первым в мире языком программирования высокого уровня. Основные концепции языка включают:

  • Наличие подпрограмм (и это в 1940-х годах!!!)
  • Наличие операции присваивания (=>)
  • Циклы
  • Условный оператор (if)
  • Возможность манипуляций с массивами
  • Возможность манипуляций со списками
При создании языка Цузе собрал множество проблем, которые были поставлены инженерами и учёными. Для демонстрации того, что язык действительно способен решать эти проблемы было написано огромное количество примеров программ (в частности около 60 страниц примеров для программы играющей в шахматы).

Одной из проблем языка был чрезвычайно сложный и очень непривычный современному программисту синтаксис. Вот пример присваивания A[5] = A[4]+1 на языке Plankalkül:


Здесь V - это строка для индексов, S - строка для задания типов данных, 1.n - обозначает целое число размером n бит.

В настоящее время институт Цузе в Берлине создал компилятор языка Plankalkul. На сайте института также представлены тексты работ Конрада Цузе и симуляторы созданных им компьютеров.

Plankalkül не оказал существенного влияния на другие языки. Но тем не менее историческое первенство - за ним.

четверг, июня 14, 2007

Комментирование и системы контроля версий

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

Ситуация эта выглядит примерно так. Программисту хочется внести какое-то изменение в код, и он поступает следующим образом: комментирует старый кусок, а затем вставляет на его место исправленный. Таким образом в исходном файле остаются ОБА куска кода одновременно.

Мне кажется, что такой способ комментирования плох в двух смыслах.

  1. Данный вид комментирования представляет собой подмену (причём недостаточно функциональную) системы контроля версий.
  2. Данный вид комментирования неудобен для тех, кто будет разбираться в коде после вас.
Подмена системы контроля версий

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

Неудобство для "будущих поколений"

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

Дело в том, что подобные закомментированные и давно неиспользуемые куски:

  1. При исследовании кода методом поиска :-) могут вполне попасться в результаты, а значит придётся затратить дополнительное время на их изучение
  2. При интенсивном использовании сильно замусоривают код, что также создаёт дополнительные сложности
  3. Комментарии многими воспринимаются как пояснение относительно работы данного куска кода (и правильно воспринимаются, именно для этого комментарии и нужны). Поэтому закомментированная часть кода, если комментарий был использован вместо системы контроля версий, может вызвать у читающего затруднения с пониманием - зачем здесь комментарий? может быть кто-то что-то тестировал и забыл убрать комментарий? Короче говоря, возникает лишний повод задуматься.

Мой общий вывод из вышеизложенного такой (нагло подделываясь под классика):
"Commenting code out considered harmful". Неиспользуемый код нужно удалять, а не комментировать. Конечно, всегда бывают "ситуации" и мы здесь говорим о каком-то общем, "среднем" случае.


P.S. Да, современные интегрированные среды разработки позволяют достаточно легко бороться с перечисленными выше недостатками (outlining; поиск с использованием регулярных выражений; интеллектуальный поиск, понимающий что комментарии нужно пропускать). Но они же часто содержат функции, позволяющие вообще не заниматься подобным комментированием, например IntelliJ Idea содержит замечательную функцию Local History, являющуюся по сути постоянно включённой системой контроля версий.

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

понедельник, июня 11, 2007

Тони Хоар: советы выпускникам

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

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

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

P.S. Тони Хоар сейчас работает где бы вы думали ... ну конечно в Microsoft Research.

среда, июня 06, 2007

Skype vs. IIS 5.1

Сегодня возникла необходимость установить на домашней Windows XP машине IIS. Установил, открыл snap-in Internet Information Services, и увидел что 'Default Web Site' не запущен. Нажал 'Start item'. И тут же увидел потрясающее сообщение об ошибке:

Unexpected error 0x8ffe2740 occurred.

Поиск известно где показал мне следующую статья в MS knowledge base:
http://support.microsoft.com/kb/816944

Статья эта говорит нам о том что подобное сообщение возникает в случае, если существует конфликт по TCP портам - какая-то программа уже использует порт, прописанный в Default Web Site. Там по умолчанию прописан конечно порт 80.

Ну дальше все уже наверное очевидно из названия поста. В лучших традициях Mark Russinovitch я запустил его замечательную утилиту Process Explorer и после недолгого изучения обнаружил:



То есть как видно Skype использует 80 порт. В настройках Skype видно следующее:



Это-то как раз и есть причина проблемы. Следовательно для того чтобы избежать описанной проблемы нужно либо выключить соответствующую галочку в Skype (и перезагрузить его), либо поменять порт по умолчанию в IIS Default Web Site.

P.S. На моей машине также (в тестовых целях) установлен пакет Денвер, представляющий из себя "набор дистрибутивов и программная оболочка, используемые Web-разработчиками (программистами и дизайнерами) для отладки сайтов на «домашней» (локальной) Windows-машине без необходимости выхода в Интернет". Денвер это, в частности, Apache - так вот ему наличие Skype не мешает, все нормально работает ... Вот соответствующая картинка:



Возможно работает все до тех пор пока кто-то не "позвонит" в Skype на 80 порт?

вторник, июня 05, 2007

Принцип DRY

Про принцип DRY все знают. Ну даже если кто-то и не знает самого сокращения, то уж смысл известен наверняка. Напомню, DRY расшифровывается как Don't Repeat Youself. То есть "Не повторяй самого себя". Первый раз с самим сокращением я столкнулся в книге The Pragmatic Programmer: From Journeyman to Master. На самом деле принцип все мы знаем очень давно, даже если не осознавали его как "принцип" или что-то глубоко умное и философское (в Википедии принцип относится к категории Software Development Philosophies).

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

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

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

Тем не менее, во многих случаях следование этому принципу сильно может облегчить жизнь программистам работающим над проектом. Сузим немного область применения принципа (авторы указывают что его можно применять буквально ко ВСЕМ составляющим ПО - не только исходному коду, но и документации, системам сборки, требованиям и так далее).

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

Откуда берутся такие ошибки? Кто в них виноват?

Программисту, которому необходимо добавить новое поле в диалог плюётся "Вот "@#$%^&*! Ну кто так пишет! И диалога два, и поведение в них чуть-чуть разное и по разным принципам они написаны, и сопутствующие классы разные!" После этого он открывает историю в системе контроля версий, смотрит фамилию предшественника и ... Ну сами понимаете. Тут уж предшественнику вполне может достаться по первое число. Зачем скопировал? Почему все то же самое, но чуть-чуть по-другому?

И что потом делает наш гипотетический программист? Вставляет исправления в ОБА места. Почему в оба? Почему он не слил два диалога в один? Ну понятно почему. Потому что у него сроки, потому что у него следующая работа, потому что у него начальство, потому что разбираться где ещё используются эти диалоги нет ни времени ни желания ...

А потом наступает момент когда кому-то нужно добавить в диалог ещё одно поле.

Виноват ли наш гипотетический программист? Или может быть виноват "самый первый" программист - тот кто из одного диалога сделал два? Зачем он так сделал?

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

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

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

Поэтому в следующий раз, если увидите две разных реализации одного и того же не торопитесь ругать программиста.