суббота, 20 декабря 2003 г.

Вверх и вниз

* * *

"В иерархии каждый индивидуум достигает

предела своей некомпетентности."

(принцип Питера)


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

Кстати замечу, что метод написания ТЗ программистами с последующим согласованием "наверху" порой дает достаточно хорошие результаты. Решения получаются лучше, чем если "менеджер проекта" выдаст это ТЗ "из общих соображений". Задача оказывается видна с двух сторон, а у руководителя появляется возможность услышать свою задачу, произнесенную чужими словами, понять, как услышали его самого, да и заметить то, о чем он забыл упомянуть. Однако, при всех преимуществах метода он применяется достаточно редко. Почему?

Да потому, что у программистов редко получается написать это самое ТЗ в нормальном виде (или в разумные сроки). Гуру от менеджмента говорят о "нисходящем" и "восходящем" проектировании, о том, что у большинства программистов другие стратегии мышления и что пусть уж ТЗ пишут другие люди, мыслящие другими масштабами обобщений... Но если вдуматься в этот тезис, он предстает абсурдом. Поскольку у "программиста" не может быть только одной стратегии мышления. Кроме того, что он программист, он еще и человек... и как человек, ловит рыбу или выбирает продукты в магазине ничуть не хуже того самого менеджера. И только на работе, садясь за клавиатуру, они включают разные стратегии. Ну так это, на мой взгляд, дело поправимое. О чем собственно и пойдет речь - о стратегиях...


* * *

"Все, что мы можем помыслить -

существует. Оно реально именно

в силу нашего представления."


Вам проще начинать разработку снизу (а дальше - что вырастет, то вырастет)? Вы можете написать код, но затрудняетесь сказать, как это все потом будет выглядеть? Отлично! Начнем.

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

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

Итак, у вас перед глазами один квадратик. А теперь представьте, что это модуль у вас УЖЕ НАПИСАН. Можете прежставить дискету в руках, файл на диске или открытый исходник в редакторе. Так или наче, но он у вас есть. Что вы с ним будете делать дальше? Тестировать, записывать в архив, может быть, еще что-нибудь... Представьте, КАК вы делаете это... Обведите ваш квадратик еще одной жирной рамочкой - пока закончено.

А теперь, _имея этот модуль уже законченным_, что вы станете писать дальше? Что есть то следующее, что вы стали бы кодировать? Руки на клавиатуре, представьте перед собой открытый редактор, о чем будет следующая строчка вашего кода? Как это "нечто" мы назовем? Рисуем следующий квадратик...

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

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

Ну вот, теперь у вас уже два модуля. Правки внесены, связи использованы... Что пишем двальше? Рисуем третий квадратик... И снова - хорошо представить, как вы будете чувствовать себя, что видеть и слышать, когда третий модуль будет написан. Остановитесь и вчувствуйтесь в этот момент, в это время, в это состояние... Каковы связи между всеми тремя модулями? Какие правки потребуются в первом и втором. Линии связей, почеркушки правок... и идем дальше.

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

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


* * *

"Не умножайте сущностей

сверх необходимого."

("бритва Оккама")

"Любая классификация содержит

от трех до шести категорий"

(из законов Мэрфи)


У нас получилась схемка. Аккуратненькая и даже (возможно) красивая. Но та ли это программа, которая нам нужна? Возможно, еще нет... Могу вам сказать, что если на вашей схеме больше 5-6 модулей, то это модули разных уровней. Некоторые из них отражают действительно существенные блоки и функции, а некоторые - частные переходики, связки и функции, про которые в какой-то момент забыли, а потом вспомнили (или наоборот: нарисовали раньше, потому что было понятнее, как их писать). Берем третий лист и перерисовываем схему, объединяя более мелкие и частные кусочки с теми модулями, к которым они собственно и относятся. У вас должно получиться от 4 до 6 модулей.


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

И остается только пройти этот путь шаг за шагом. Если так, то стоит вернуться назад, ко второму листу и еще раз рассмотреть эти крупные модули, задавая себе все тот же вопрос: "с чего именно я начну писать эту штуку?" При этом крупный модуль распадется на несколько более мелких. После этого можно будет вернуться к сборке схемы на один уровень крупности. Замечу попутно, что все вновь полученные модули должны иметь свои собственные имена, как всякие вещи, вновь рожденные нашим воображением (и Адам начал работу по именованию всех тварей земных...), ибо то, чего мы не можем помыслить, не существует.


* * *

"Бутерброд всегда падает маслом вниз"

(первое следствие закона Мерфи)


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


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


Ну вот, теперь можно писать... нет, нет, не код. Техническое задание.


* * *

"... все уже было."

Положите перед собой ваши листочки. Если вы возвращались к переразбивке модулей, то оставьте толко "основную ветвь" (тупиковую можно отложить в сторону). Кстати, листочков у вас окажется тоже 4 - 6, как и модулей... ("Части кота, - подумал кот. - Усы... лапы...")

И начинаем описывать существенные взаимодействия, следуя по листочкам в обратном порядке. Сперва - взаимодействия вашей программы с внешним миром. Здесь можно использовать куски текста из "общей постановки задачи", которая была вам дана (устно или письменно), и обязательно должны присутсвовать те ограничения, которые заставили вас внести почеркушки-"правки" на последнем этапе. Это те самые моменты внешнего мира, про которые забыли и начальство и заказчики. И одновременно - основная тема для согласований. Дальше возвращаемся к первому-второму листочку, какие правки отмечены там? Что требовалось бы сказать вам, чтобы вы сразу выбрали чистовой вариант?

Ну вот, собственно и почти все с ТЗ, остальное - нюансы оформления, которые в каждой фирме свои.

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

20.12.2003

пятница, 18 июля 2003 г.

"Мифотворцы"

"Я включил кибернетику в
качестве второго важного
исторического события моей
жизни, поскольку у меня есть [...]
смутная надежда, что мы
сможем заставить себя честно
пользоваться этим новым
пониманием. Если мы будем хоть
немного понимать, что мы
делаем, может быть, это
поможет нам найти выход из
того лабиринта галлюцинаций,
который мы создали вокруг себя.
"
(Г.Бейтсон 1966г.)

Я пишу эту заметку через 37 лет после слов Бейтсона, и пишу ее, может быть, именно потому, что вижу надежды Бейтсона не оправдавшимися. Хотя есть "время разбрасывать камни, и время собирать камни; [...] время искать, и время терять; время сберегать, и время бросать" (Еккл.). Возможно, время слов Бейтсона еще не пришло? Какое время сейчас?

Программа как метафора
"Тот, кто верит в реальность
вещей, живет в совершенно
нереальном мире.
"
(Сутра Помоста)

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

Возьмем простой пример - функция "выделения памяти". Вы думаете, "память" вам действительно "выделяют"? Отрезают кусочек от микросхемы и кладут на весы? Нет, разумеется, вы так не думаете... Вы, возможно, знаете, что "выделение памяти в большинстве библиотек..." Стоп! Какая разница, как оно реализовано? Вопрос - что есть такое "выделение памяти"? А есть мы будем метафору некоторых операций над некими сущностями.

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

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

- Вы пробовали записать "Белоснежку" на языке CASE-средств? Уверяю вас - это возможно. - Не пробовали? Что ж, это говорит в пользу вашего вкуса. ("- Мне беленькие, простые. - У вас потрясающе хороший вкус".) Впрочем, можете посмотреть формальный язык записи фольклорных сюжетов. Но насколько мне известно, при написании сказок писатели его не используют. И если заглянуть в "курилки" некоторых программистских фирм, да отследить потом судьбы продуктов... приходит мысль, что лучшая постановка - та, что может быть рассказана устно, в форме метафоры, образа, истории. И постановка действительно понята программистом, если он может пересказать образ своими словами. Качество постановки - качество фольклора, его жизнеспособность.

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

Сценография
"Если хорошо подумать, все
это смахивает на балаган.
"
(Хуэйкай) *
Итак - сказав А, пора говорить Б. Если мы имеем дело с представлениями "сказок", то скорее всего мы с вами в театре, или если без лишнего формализма - в балагане. А потому законы жанра диктуют свои правила. В частности - правила постановки вопросов. Например, если на стене висит ружжо, то висит оно там не "потому что", а "для того чтобы". Для того, чтобы разгневанному главному герою в четвертом акте было что хватать. Так и сущности, встречающиеся в программах, могут быть оправданы только целью, но никак не историей. Я говорю "оправданы", поскольку бритва Оккама отсекает все лишнее, как в познании, так и в творчестве.

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

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

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

На пути к мифу
"Нет науки без бессознательных
предпосылок, над которыми
никакой исследователь не имеет
власти...
"
(О. Шпенглер) *

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

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

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

18.07.2003

------------------------
* Цитаты взяты по книге В.Ирхин М.Кацнельсон "Крылья феникса"