|
Свежий номер №23 (400) / В качестве оправдания за свою статью в номере 16 (393) Дата публикации: 19.06.2001 Сергей Козлов, teleman@elnet.msk.ru
Понимание проблемной области Если задача проработана, хорошо формализуется, а ее решение сводится лишь к элементарной штамповке, доработке, подгонке, подрихтовке почти готовых решений, то действительно стоит по максимуму воспользоваться опытом и результатами труда прошедших этот путь, не изобретать велосипеды и т.д. Идти по пути грамотного применения уже отработанных решений. И какая-то доля (и вполне заметная) задач укладывается в эти рамки. Но, на мой взгляд, интересными и благодатными представляются не те области, где для простых или типовых задач обычно уже есть готовые (или почти готовые) решения, но те, где программный проект затевается для решения действительно сложных и/или уникальных задач. Либо обнаруживается ниша, для которой еще нет адекватного типового решения. Это ведь более сильное стратегическое решение для программистской фирмы, чем конкуренция со многими похожими как близнецы типовыми решениями. Сложные задачи плохо формулируются, присутствует множество параметров и критериев, многие проблемы сначала просто не видны или не осознаются. Они не решаются одним кавалерийским наскоком. Если исходить из "стандартных" решений, то бездумное их применение (т.е. принудительное втискивание решений в рамки задач) обычно влечет за собой громоздкость и дополнительную сложность, перемножающуюся со сложностью самой проблемной области. Громоздкое решение содержит больше трудноустранимых ошибок, хуже сопровождается и с большим трудом развивается. В этом смысле понимание подразумевает получение "правильного" (соответствующего действительности) представления о проблемной области и согласование концепции проекта с этим представлением. При этом думается, что это ведет к элегантным, красивым, компактным, понятным решениям. Механическое применение подходов без понимания - путь против Природы, следствие чего - значительные усилия в попытках ее преодолеть. Понимание дается не сразу, а постепенно, и лишь если к этому стремиться. И, как следствие, первоначальное решение наверняка не будет адекватным, поэтому вполне вероятно, что в процессе работы как результат возросшего понимания может появиться стратегически более "правильное" решение, реализация которого может повлечь изменение концепции. В качестве иллюстрации можно сравнить первоначальное сложное и запутанное описание перемещения планет с помощью эпициклов (в предположении неподвижной Земли и перемещающихся вокруг нее планет и Солнца) и гораздо более простое представление при появлении современной гелиоцентрической модели Солнечной системы. Аналогичные находки наверняка существуют и находятся (если их искать!) в любой предметной области. В этом смысле мне показалось "неправильным" не утверждение о как можно более быстром начале выпуска версий (поскольку это позволяет быстрее столкнуть проект с действительностью), а сочетание этого утверждения с подходом "от молотка" (а не от проблемной области), усугубляемое чрезмерной заботой о стабильности проекта, особенно на начальных стадиях разработки. Т.е. плох не ранний выпуск версий, плох ранний выпуск без предшествующего осмысления проблемной области, соединенный со стремлением закрепить первоначальные решения (особенно уже "отлитые в коде"). И отказ от умеренно революционных изменений в пользу слабо эволюционных. Адекватность отражения понимания Другой важный аспект - это "пересказ". Т.е. в условиях каждой роли присутствует не взаимодействие непосредственно с действительностью, а взаимодействие с несколькими ограниченными "пересказами" действительности. Заказчик излагает свое понимание, менеджер проекта его перерабатывает в меру своего понимания проблемной области и своего понимания возможностей разработчиков, переформулирует, специфицирует, менеджер программы этот пересказ разжевывает разработчикам, разработчики реализуют свое понимание этого пересказа, тестеры изучают продукт как "черный ящик" (не интересуясь тем, что же он делает на самом деле), в конце концов продукт попадает к пользователям, а их мнения опять через целую цепочку пересказов попадают к разработчикам. Это называется "испорченный телефон". Все усугубляется еще и тем, что под флагом повышения эффективности добавляются вспомогательные коммуникационные посредники-клерки. А менеджеры узнают о работе подчиненных лишь понаслышке (в виде искаженного желанием избежать ответственности пересказа). Не удержусь от иллюстрации.
Еще один аспект - это добывание понимания "избранными". Разделение на "избранных понимателей" и "добросовестных исполнителей" означает, что мыслительные возможности коллектива не используются в полной мере. Т.е. понимание не поощряется, не считается необходимым (ему как бы "запрещается" присутствовать) на всех уровнях и этапах разработки. Альтернативой этому могло бы стать "распределенное" объединение творческий способностей, когда результат объединения способностей превышает их арифметическую сумму, поскольку точки зрения отличаются. Взаимопонимание, совместное формирование понимания и совместное использование понимания дает "голографический" эффект, в отличие от "фотографического", при котором сбегание ценного сотрудника означает (часто фатальную) потерю необходимого для завершения проекта знания и умения. В "голографическом" случае отламывание кусочка делает картинку чуть более размытой, а не ведет к полному исчезновению фрагмента. Представляется неправильным отделение разработчиков от реальности проблемной области. Обратная связь должна (при необходимости, но не по обязанности) идти не через посредников, а напрямую. Лучше один раз увидеть, чем сто раз услышать. Эффективное использование ресурсов С точки зрения эффективного использования "человеческого ресурса" очень важны, на мой взгляд, следующие аспекты. Высокая мотивированность в достижении цели - успешного проекта. Что в немалой степени определяется степенью вовлеченности. Когда человек работает просто от и до, опасаясь лишь надсмотрщиков, а его творческие способности при этом задействованы по минимуму, он лишь исполнитель инструкций. И о вовлеченности тут говорить трудно. Если творчество востребовано на рабочем месте, то рабочие места займут творческие, думающие люди. Если нет - "кодирующие обезьяны". Непосредственное взаимодействие заинтересованных сторон. Это подразумевает устранение ненужных посредников и живое взаимодействие. Например, на пресловутом стыке кодирование-тестирование, это означает разработку для тестирования и проведение тестирования тестером и разработчиком вместе, параллельно. Когда я упоминал такой инструмент как отладчик - то это не отладка, а именно тестирование отлаженного кода с использованием отладчика (хотя не настаиваю именно на таком методе). Программа тестируется на соответствие спецификации, ТЗ. Но не как "черный ящик". Гоняется программа, и одновременно, синхронно с ее работой изучается ее код, и мы убеждаемся, что этот код не только соответствует спецификации, но делает именно то, что нужно, в нем нет побочных эффектов (которые не проявляются в данном тесте, но окажутся разрушительными при других обстоятельствах, и хуже всего, если только после сдачи в эксплуатацию). [Есть требования заказчика - есть ошибки проекта (неправильное разделение на подсистемы, не соответствующая задаче архитектура, невыполнение требований к системе и т.д.), есть проект системы - есть ошибки спецификации подсистемы, есть спецификация подсистемы (unit) - есть ошибки ее реализации (реализация не соответствует спецификации), наконец, есть ошибки кодирования. Все это ошибки. И тут всплывает тонкость отличия unit testing и usage testing. Ведь ошибки, пропущенные на стадии unit testing, становятся ошибками, отлавливаемыми на стадии usage testing. Плюс ошибки, проявляющиеся только на стадии usage testing.] Обычно проявления последствий ошибки распространяются. Быстрое (на месте) исправление "простых" ошибок ведет к более продуктивному кодированию и тестированию (обратная связь). В какой-то степени это напоминает парное программирование в eXtreme Programming - более быстрое прокручивание спирали разработки без посредников. Другая вариация более быстрой прокрутки - тестирование после каждого шага разработки (после внесения согласованных изменений в код программы, например при реализации какой-то задачки, пунктика спецификации). Внесение сразу большого количества разнородных изменений приводит к лавинному проявлению ошибок, а их выявление при тестировании оборачивается фактически случайным поиском. Более быстрый цикл разработка-тестирование сокращает, и даже устраняет лавину, делает тестирование более осмысленным. При достаточной степени ответственности (и доверия) разработчик в какой-то части способен выполнять тестирование сам, хотя ему может понадобиться помощник-собеседник. И нет речи о бесполезности тестеров в "традиционном" понимании! Они необходимы как носители другой точки зрения. Возможно, и представляется желательным, взаимодействие не на уровне административно зафиксированных ролей, а динамичное формирование групп по атомам познания из работников, административно (по ролям) подчиненных разным менеджерам. Их совместная работа на основе взаимодействия, взаимодополнения, а не противостояния или конкуренции, служит (через сотрудничество) достижению общей цели. В случае "конкуренции" мы на самом деле размазываем цель на множество эгоистичных подцелей, которые вовсе не обязательно дадут в результате требуемое движение к единой цели. Минус затраты сил на противодействие чужим эгоистичным подцелям. Роль менеджеров при этом - роль рефери, разрешающих конфликты, которые не удается устранить на "нижнем" уровне самостоятельно. Все вышесказанное не отменяет того, что
Изложенные моменты, как правило, недооцениваются и/или просто игнорируются в общепринятых "индустриальных" подходах, что губит сами подходы. Но программирование - это все-таки деятельность ума, а не тела. И человек, и его подходы должны совершенствоваться.
|