Производство варева
АрхивВ те далекие уже времена, когда диски были большими и каждому хватало 640 килобайт памяти, мне пришлось заниматься измерением параметров случайного сигнала от некоей установки.
«Суть» очерчивается тогда, когда при сравнении двух каких-либо качественных характеристик нам вдруг открывается что-то новое про каждую из них. Колин Уилсон |
«Ну вот, опять про кулинарию», — скажет внимательный читатель, вспомнив недавний номер «Компьютерры» (#472, «Шарим? Варим!»). И будет прав. Только сегодняшняя тема не о тонкостях «кустарного» изготовления «варева», а о подходах и техниках его производства сплоченными программистскими командами. К сожалению, не все интересные вопросы удалось затронуть в теме номера — задача была иная: сделать введение в теорию и практику разработки софтверных проектов. Вадим Иванченко |
В те далекие уже времена, когда диски были большими и каждому хватало 640 килобайт памяти, мне пришлось заниматься измерением параметров случайного сигнала от некоей установки. Казалось бы, существуют развитые статистические методы, были даже готовые библиотеки… Загвоздка оказалась в том, что сигнал дрейфовал и, соответственно, применение описанных во всех учебниках методик давало в результате полнейшую чушь, — рассчитаны-то они на стационарные процессы. То столкновение с реальностью дало хороший урок — методики и инструменты бесполезны без понимания предмета, с которым имеешь дело.
Поэтому, прежде чем говорить об организации разработки ПО, чудодейственных методологиях и прописанных до мелочей процессах, зададимся такими вопросами «Почему методологий много? Чем они отличаются? Из каких предпосылок, из какой модели предметной области они исходят? Каковы их области применимости?».
Три составные части
Возникает новое представление о неразрывном единстве, отрицающее классические понятия о том, что мир можно разложить на самостоятельные, не зависящие друг от друга части…
Дэвид Бом
Почему вообще появляются программы? Прежде всего потому, что во Вселенной есть люди, желающие решить свои проблемы применением, например, не автомата Калашникова, а некоего «компьютера». Если они сами не могут, то привлекают группу людей, способных решить их за конечное время и конечное количество безусловных тугриков. Если проблемы решаются написанием кода для компьютера, эту группу людей называют программистами.
Вот у нас и появились действующие лица и исполнители. Пользователи-люди, действующие в своей предметной области и решающие свои проблемы. Инструменты-компьютеры, работающие под управлением написанных программистами программ, взаимодействующие тем или иным способом с пользователями и их предметной областью и исполняющие их желания. Программисты-люди, изучающие предметную область и желания пользователей и создающие программы, которые запускаются на компьютерах пользователей и исполняют их желания. Предметная область, или реальность, в которой все это происходит, которая изменяется под воздействием людей и систем и которая оказывает воздействие на людей и системы, вызывая у пользователей новые проблемы. Ну и так далее.
Мы вытащили из клубка некие сущности. Попытаемся их охарактеризовать.
Пламень теорий
и ледяная вода практики
Прогресс состоит не в замене неверной теории на верную, а в замене одной неверной теории на другую неверную, но уточненную.
Стивен Хокинг
Реальность динамична, нестационарна, нелинейна. Но она познаваема. Люди находят в ней закономерности и строят ее модели. Создавая теории реальности, люди достигают некоторого уровня понимания ее семантики и, вооружившись этим пониманием, узнают, как исполнить свои желания, а затем превращают это знание в программы.
Не каждая модель пригодна для реализации в виде программы. Если посмотреть в корень, то компьютер есть материальная реализация математики, а программа представляет собой записанную на языке программирования формальную теорию. Это накладывает большие ограничения. Латвийский математик Карлис Подниекс пишет по этому поводу, что для математического подхода к решению какой-либо проблемы «характерно прежде всего стремление как можно скорее «покончить с реальностью», перейти к исследованию определенной (фиксированной) математической модели. <…> Застывшая система основных принципов — отличительная особенность всякой математической теории. <…> Всякая формальная теория с методологической точки зрения является моделью некоторой застывшей системы мышления. С учетом этого основной вывод из теорем о неполноте можно переформулировать так: всякая достаточно всеобъемлющая (фундаментальная?), но застывшая система мышления неизбежно оказывается несовершенной — в ней содержатся либо противоречия, либо проблемы, для решения которых данной (застывшей!) системы недостаточно».
Два важных следствия теоремы Гёделя о неполноте. Единственная возможность вырваться за пределы математической теории — воспользоваться способностью человека исследовать и мыслить. Не сопровождаемая, не развиваемая программа — мертвая программа.
Дилемма Вуглускра
Дедуктивная логика тавтологична; с ее помощью нельзя постичь новую истину, она манипулирует ложными утверждениями с той же готовностью, как и верными. Если ты забудешь об этом, она может сыграть с тобой шутку, причем идеально логичную. Конструкторы самых первых компьютеров называли это GIGO — «мусор на входе, мусор на выходе». Индуктивная логика куда более трудна, но она позволяет постичь новую истину…
Роберт Хайнлайн
Когда мы пытаемся получить описание или представление чего-либо, то используем объекты (существительные, данные) и действия (глаголы, алгоритмы). И оттого, что считаем «главнее», получаем два подхода.
Первый, так называемый процедурный (действие-ориентированный) подход, сводится к тому, что у нас есть данные — начальное состояние системы, — над которыми мы совершаем некоторую последовательность действий и в результате достигаем нового состояния этих данных. Если мы знаем начальное состояние, желаемое конечное состояние и находим последовательность действий, переводящую из одного в другое, то задача решена.
Второй, объектно-ориентированный, состоит в том, что мы выделяем некоторые сущности, объекты, и наделяем их переменными состояния и методами, которые эти переменные изменяют. Затем мы описываем систему как совокупность взаимодействующих объектов.
Однако в любом случае мы остаемся в рамках формальной теории. Мы не получим нового знания, преобразуя представление дедуктивным методом (математическая индукция — частный случай дедукции). Оно привносится извне — изменением формальной теории. Тут работает (неполная) индукция — человек догадывается, открывает нечто, основываясь на неполных данных. Это творчество. И тут есть тонкий момент — индукция не поддается формализации, и мы не можем создать математическую теорию творчества, она всегда нематематическая.
У индукции много недостатков, но, по-видимому, это единственный доступный человеку способ создать что-то новое. Мы можем не угадать, выдумать несуществующее, воспользоваться ложной аналогией. Поэтому очень важно убедиться, что мы угадали правильно и находка действительно свойственна изучаемой предметной области, а не артефакт воображения. Проверить это можно лишь экспериментально — необходима обратная связь с реальностью. Попытки сначала спроектировать, а потом реализовать по строгому плану нередко обречены на провал — мы проектируем, еще не зная, с чем имеем дело. Поэтому разработка — не прямой, как стрела, легко прогнозируемый процесс, она, как поросячий хвостик, — итеративная: мы выдвигаем гипотезы, проверяем их, отбрасываем негодные, строим новые. Изменяя мир, мы изменяемся сами — мы учимся.
Вдохновение повара
и кулинарные рецепты
Если бы они знали, что мы делаем, они не называли бы это исследованием.
Альберт Эйнштейн
С точки зрения компьютера, любую формальную теорию можно реализовать и объектно, и процедурно — в этом смысле оба подхода эквивалентны. В изменяющейся во времени системе нет объектов без действий и нет действий без объектов. Просто это два способа посмотреть на одно и то же.
С точки же зрения человека, при поиске понимания (особенно сложных систем) удобнее обращаться с объектными моделями, при планировании деятельности (особенно краткосрочной) — с процедурными. Для понимания бывает очень полезно посмотреть с обеих точек зрения. По-видимому, оптимальная стратегия — поняв, спланировать действия. (Планировать нужно, как минимум, чтобы оценить время и стоимость работы.) Не всегда это просто. Поэтому выбирается тот или иной подход, в котором делаются некоторые упрощающие предположения. Выделим такие:
- Реальность: познаваема или непознаваема.
- Обратная связь: с реальностью или с формальной моделью реальности.
- Работа: достижение понимания или следование процессу.
- Подход: застывший («предсказуемый») или адаптивный.
Интересно, конечно, заняться анализом всего этого морфологического ящика, но назовем лишь три варианта:
A. Реальность — это хаос, в котором невозможно разобраться. Не царское это дело, у нас планы, сроки. Что думать — трясти надо. Другой способ — следовать написанному кем-то рецепту без понимания. И его разновидность — «подход от молотка»: инструмент есть, а дело ему найдется.
N. А чего тут неясного? Вот умные дяди написали — берем, и вперед. Особенно опасен выбор первой попавшейся модели (не все модели адекватны задаче сейчас и будут адекватны потом). Дальше работа идет не с реальностью, а с ее формальной моделью.
D. Реальность познаваема, но нельзя дожидаться, когда будет построена полная и окончательная модель, а только потом браться за проект. Нужно с чего-то начинать, какая-то модель лучше, чем вообще никакой, но ее необходимо уточнять и совершенствовать. Критерии: соответствие (адекватность), обозримость (компактность и простота, необходимость и достаточность), тестируемость (проверяемость). Программа — это теория программиста о предметной области.
eXtreme Programming |
Котелок, вари
Любой человек должен уметь менять пеленки, планировать вторжения, резать свиней, проектировать здания, управлять кораблями, писать сонеты, вести бухгалтерию... утешить умирающего, решать уравнения, анализировать новые проблемы, вносить удобрения, программировать компьютеры, вкусно готовить, хорошо сражаться, достойно умирать. Специализация — удел насекомых.
Роберт Хайнлайн
Конечно же, программы делаются не пальцем. Нужны инструменты, и много — арсенал. Как вехи в развитии инструментов назовем машинный код, языки высокого уровня, структурное программирование, объектно-ориентированное проектирование и программирование, обобщенное программирование, компоненты, паттерны проектирования. Но кисть не рисует сама, ее держит художник.
Программист может сделать все один, если задача ему по силам, если он не ограничен временем и т. д. Для больших проектов программистов объединяют в команды, фирмы, корпорации. Разделение труда и все такое. Сразу появляется множество проблем, которые нужно решить, чтобы работа была эффективной. Производительность команды не равна производительности одного программиста, умноженной на их число (об этом писал еще Фредерик Брукс в книге «Мифический человеко-месяц»). Человек тоже динамичный, нестационарный и нелинейный.
Выделим несколько проблем, которые по-разному решаются в разных подходах1 (интересно отметить аналогии в подходах к проектированию и к организации разработки):
1. Критерии разделения труда: функциональные роли («взаимозаменяемые совместимые программирующие устройства») или архитектура проекта.
2. Взаимодействие внутри команды: бюрократический процесс или распределенное понимание, бумаготворчество или живое творческое общение.
3.Общение с клиентами и консультантами в предметной области: через посредников или живое.
Вообще, человек-программист — очень интересная и, что удивительно, мало исследованная тема. Здесь же просто сошлюсь на перевод живой и интересной работы Алистера Кокберна «Люди как нелинейные и наиболее важные компоненты в создании программного обеспечения»2
Бульон в кубиках
Точное описание человеческого прогресса: едва ты выясняешь, как следует поступать, как обнаруживается, что уже поздно. Однако порой бывает, что накопленные знания удается потом использовать для решения уже новой проблемы. В противном случае мы сейчас еще качались бы на ветках.
Роберт Хайнлайн
Эта статья писалась как вводная, и я не делаю обзора конкретных подходов (их множество), а отсылаю читателей к работе Мартина Фаулера «Новые методологии программирования»3 и предлагаю самостоятельно выяснить, как затронутые проблемы решаются в конкретных методологиях.
Какая из существующих методологий самая правильная? Мне кажется, этот вопрос не имеет смысла. А на «почему?» отвечу словами Фаулера: «Вдохновение и базовые знания можно черпать из уже известных процессов и собственного опыта, тогда как окончательная адаптация процесса к выполняемым в настоящий момент задачам относится к сфере профессиональной ответственности разработчиков». Конкретным задачам, конкретных разработчиков.
1 Этих вопросов я уже касался в статье www.computerra.ru/offline/2001/400/10578.
2 www.maxkir.com/sd/people_as_nonlinearRUS.htm.
3 Ее перевод см. www.maxkir.com/sd/newmethRUS.html.