На старт! Внимание! И?

18 сентябрь, 2005 - 23:00Андрей Зубинский

Что делать? Как делать? Чем делать? Все эти вопросы на самом деле вторичны. Искать ответы на них следует только после утвердительного «Делать!», уверенно сказанного в ответ на Вопрос Вопросов «А делать ли вообще?» Талантливый программист Йон Смерл (Jon Smirl) начал искать ответ на этот вопрос слишком поздно – когда груз добровольно взваленного им на себя проекта Xegl стал настолько непосилен, что хороший проект пришлось закрыть.

Пожалуй, начинать придется с повторения очевидного. Оценка стоимости программного продукта – не разовое действие, а процесс, сопровождающий разрабатываемый, а затем и созданный продукт на всех этапах его жизненного цикла. Именно поэтому даже принято говорить об отдельных жизненных циклах собственно продукта и оценки его стоимости. Последняя уточняется даже тогда, когда в нее вносятся необходимые коррективы, отражающие затраты, связанные с выведением продукта из употребления. Естественно, можно ограничиться макроуровнем – выделить отдельные фазы этого процесса и сконцентрироваться на них. Так, наиболее интересной является предпроектная фаза, позволяющая оценить – пусть грубо, но все-таки хоть с какой-то степенью определенности – сложность и стоимость будущего программного изделия. К сожалению, незнание практикующими программистами сравнительно простых вещей и отсутствие в обязательных курсах обучения дисциплин «программной метрологии» приводят к тому, что упорно не желающие сдаваться перед натиском индустриального подхода к разработке ПО многочисленные «частники-индивидуалисты» (создающие будь то Open Source, будь то shareware-программы) переоценивают свои силы и расходуют время на проекты заведомо нереальной сложности. А понимание напрасности израсходованных времени и сил всегда приводит к разочарованию – виновнику маленьких и больших житейских трагедий. С другой стороны, тем программистам, кто уже вырос из коротких штанишек кодирования и присматривается к управленческой работе, но все же – по специальности, очень полезно иметь представление об оценке стоимости программного продукта и проекта по его созданию.

Сразу следует предупредить читателя, в первую очередь, владеющего каким-либо языком программирования и имеющего за плечами определенную практику разработки ПО, – область, в которую мы вторгаемся, находится за пределами традиционно очерченной «дисциплины программирования». Эту область можно отнести к нечетко очерченной территории «архитектуры» (более точно было бы применить английский термин, не имеющий точного перевода и даже аналога, – architecting). Название области – пользовательские требования к функциональности (functional user requirements, в дальнейшем автор постарается все специфические термины приводить в оригинальной форме – это просто необходимо в связи с тем, что русскоязычной литературы соответствующей тематики очень мало). «Расстояние», отделяющее две области – специфичный для программиста мир программных решений и мир пользовательских требований к функциональности (ПТФ), огромно. Понятийный аппарат программистского мира предназначен для нахождения способов реализации программ, в мире же ПТФ реализация неинтересна и несущественна, здесь главное – точное нахождение всех ответов на вопрос «что программа должна делать?». Соответственно, начинать надо со знакомства с терминами, которые в мире ПТФ звучат привычно, но специфика их семантики отражает расстояние между двумя упомянутыми областями.

Непривычные смыслы

Всего можно выделить шесть терминов, синтаксически совпадающих в двух мирах. Начнем мы с самого распространенного. Казалось бы, что может быть необычного в слове «пользователь» (user)? Программисты (да и в целом IT-специалисты) настолько привыкли понимать под ним человека, взаимодействующего (или использующего) программу, что в более чем неплохих словарях (например, Microsoft Computer Dictionary, изд. 5-е, 2002 г.), отдельного определения для термина «user» просто нет. В мире пользовательских требований к функциональности «пользователь» уже намного менее конкретен – им может быть не только любая персона или группа/организация, влияющая на формирование требований (т. е. способная сформулировать один или несколько ответов на вопрос «что должна делать программа?»), но и вообще все, что взаимодействует в любой форме в любое время с программой. Иными словами, «пользователем» могут быть люди, группы людей, организации, приложения, а также все объекты любой природы, являющиеся источниками и потребителями данных программы. Так, для проектировщика встраиваемой микрокомпьютерной системы безопасности пользователями вполне могут быть... ночные бабочки и, простите, тараканы. Потому что и те и другие существа могут с высокой степенью вероятности вносить в работу системы помехи (влияя на распространенные типы датчиков), которые надо учитывать при формировании требований к функциональности. И точно такими же пользователями в этом случае будут контроллеры соединенных с системой безопасности удаленных точек оповещения, сотрудники охраняемого объекта и службы безопасности.

Толкование терминов «приложение» и «система» (application, system) в мире ПТФ также несколько отличается от общепринятого (табл. 1). Здесь «приложение» – это связанный в единое целое и подчиненный определенным целям набор автоматически выполняемых процедур и сопровождающих данных. «Приложение» может содержать множество компонентов, модулей, подсистем. Часто используемые синонимы для этого термина – система, прикладная система (application system), информационная система (information system). В этом определении «приложения» важен факт его независимости от типа платформы, режимов работы, способов физической организации выполнения функций. Иными словами, «приложение» в мире ПТФ совершенно лишено деталей реализации.

Таблица 1. Краткий словарь IT-ПТФ
Термин Принятое в IT значение Значение в мире ПТФ
Пользователь (user) Физическое лицо, которое использует ПО или определяет требования к нему Лицо, группа лиц, организация, приложение, устройство и т. д., которые в той или иной мере обусловливают требования к функциям, выполняемым ПО
Приложение (application) Физическая реализация программного продукта. Границы «приложения» часто четко определены сугубо на аппаратном или программном уровне Образующий единое целое набор автоматически исполняемых процедур и необходимых данных, подчиненный строго определенному перечню целей
Проект (project) В зависимости от организационных особенностей может включать в себя как процесс проектирования нового изделия, так и процессы его модификации, усовершенствований и т. д. Множество оценок функциональности и усовершенствований во всех точках жизненного цикла ПО
Файл (file) Набор данных, существующий на физическом уровне (обычно на уровне конкретной файловой системы, например «входной файл») Обусловленная пользователем как связанная группа данных безотносительно их типа, представления и физической реализации

Еще один «новый» термин – «проект». Его ПТФ-значение существенно отличается от общепринятого инженерного. Хотя бы тем, что оно основывается на дополнительном понятии – «оценка функциональности в точке» (function point count), отражающем число реализованных требований к программному продукту в данной точке его жизненного цикла. Соответственно, «проект» в ПТФ – это множество оценок функциональности во всех точках жизненного цикла ПО.

Непривычность понятия «проект» в мире ПТФ распространяется и на термин «усовершенствование в ходе проекта» (enhancement). Под ним подразумевается разница между оценками функциональности в соседних точках жизненного цикла ПО. Усовершенствования, таким образом, не обязательно могут означать появление дополнительной функциональности.

На понятии «файл» в мире ПТФ основано много определений. ПТФ-файл – это логически связанная группа данных безотносительно физической реализации данных. Что означает – ничего общего у ПТФ-файла с традиционным для IT «файлом» фактически нет. К слову, понятие «логически связанный» также имеет специфическое ПТФ-значение. Но его лучше всего пояснить так – если в литературе о ПТФ вы встретите слово «logical», забудьте о «логических моделях баз данных» или о «математической логике» и просто замените его сложным синонимом «определенный опытным пользователем как...». То есть использованное ранее сочетание «логически связанный» означает следующее: «определенный опытным пользователем как связанный».

Оценка функциональности в баллах

Определение, принятое в экономике для продуктивности (товары или услуги, произведенные с единичными затратами труда и средств), долгое время фактически «не работало» в такой сфере деятельности, как программирование, из-за отсутствия четко определенных понятий «товар» и «услуга». А распространенные оценки продуктивности, основанные на количестве строк кода, на самом деле далеки не то что от идеала, а в некоторых случаях от элементарного здравого смысла. Кажущееся неожиданным, это утверждение хорошо иллюстрируется известным парадоксом оценки производительности, основанной на «стоимости строки кода». Предположим, что два коллектива разработчиков решают одну и ту же задачу с применением разных технологических средств. Первый коллектив специализируется в низкоуровневом программировании с использованием языка ассемблера целевой платформы, второй – работает на языке C. На первых проектных этапах в силу высокой квалификации обе группы идут плечо к плечу, затратив по одному месяцу на изучение требований к ПО и по два месяца на высокоуровневое проектирование. Этап кодирования, безусловно, намного более трудоемкий при применении низкоуровневого языка ассемблера, отнимает у первого коллектива девять месяцев, у второго – два. Соответственно, по той же причине этап тестирования обходится первому коллективу в четыре месяца, второму – в два. Завершающие этапы – подготовка комплекта сопроводительной документации и отработка системы поддержки ПО у обеих команд почти одинаковы – первый коллектив затрачивает на решение этих задач три месяца, второй – два. Результирующий программный продукт первой команды содержит 30 тыс. строк кода, второй – 5 тыс. И наконец, затраты первой команды составляют 150 тыс. у. е., второй – 90 тыс. А вот теперь начнется парадоксальное – если оценивать эти два проекта на основе «строк кода», то получится, что цена строки кода при программировании на ассемблере – 5 у. е. (150 000 у. е./30 000 строк), почти в три раза меньше, чем строки кода на C, которая равна 18 у. е. (90000 у.е./5000 строк). А производительность труда программистов-«ассемблерщиков», измеренная в выданных на-гора строках в месяц, выше в три раза (!), чем у их работающих на сравнительно высокоуровневом языке коллег – 30 тыс. строк за 19 месяцев против 5 тыс. за 10 месяцев, т. е. 1579 строк в месяц против 500. И пусть логика и практика подсказывают, что использование высокоуровневых средств создания ПО лучше, метрика, основанная на «строках кода», убедительно доказывает обратное. Это противоречие в конце 70-х годов прошлого века вынудило Алана Альбрехта (Allan Albrecht) из IBM создать новую метрику, пригодную для более разумной оценки как продуктивности работы программистов, так и сложности и стоимости программного проекта – оценку функциональности в баллах. Основная идея метрики Альбрехта – максимальный отказ от деталей реализации ПО и перенос оценки в область функциональности, наблюдаемой пользователем. Иначе говоря, в область ПТФ, пользовательских требований к функциональности.

Главный инструмент оценщика функциональности в баллах – простая таблица, заполняемая на основе результатов формирования перечня требований к проектируемой системе (табл. 2).

Таблица 2. Калькулятор оценки функциональности в баллах
Параметр Весовой фактор (Cj) Оценочная функция
Оцен-ка Простой проект Типовой проект Сложный проект Баллы
Количество входных файлов X1 3 4 6 C1X1
Количество выходных файлов X2 4 5 7 C2X2
Число пользовательских запросов X3 3 4 6 C3X3
Количество внутренних файлов X4 7 10 15 C4X4
Количество интерфейсных файлов с внешними системами X5 5 7 10 C5X5
Функциональность в баллах, всего Σi CiXi

Следует учесть, что понятийный аппарат, использованный в этой таблице, соответствует не классическим, принятым в IT, толкованиям терминов, а уже упомянутой ранее ПТФ-терминологии.

Подставив в табл. 2 оценочные цифры Xi, которые легко получить из описания системы на уровне ответа на вопрос «что система должна делать?», и выбрав класс сложности проекта (здесь нужно исходить из опыта и принципа «готовимся к худшему»), можно оценить его функциональность в баллах. К слову, точность такой эмпирической оценки может быть на ранних проектных стадиях высьма высокой и достаточной для практики – по мнению специалистов, на уровне 25%.

Но сама по себе оценка функциональности в баллах явно не подходит для того, чтобы определить сложность проекта и его стоимость. И тут на помощь «оценщику» приходит метод «отката» к... оценке сложности в строках кода (в зарубежной литературе именуемый backfiring). Это эмпирический метод, позволяющий пересчитать баллы функциональности в реализующие их строки кода на основании полученных с помощью статистического анализа множества реальных проектов коэффициентов (табл. 3).

Таблица 3. Число строк кода, необходимых для реализации одного балла функциональности в зависимости от языка
Язык Строк кода на балл функциональности
Ассемблер 320
Макроассемблер 213
C 150
Algol 106
Cobol 106
Fortran 106
Pascal 91
Modula-2 71
Ada 71
Prolog 64
Lisp 64
Forth 64
Basic 64
C++ 53
Java 2 46
Objective C 26
Visual Basic 6 24
Smalltalk 21
Delphi 5 18
Языки запросов 16–13

Данные в табл. 3 интересны не только возможностью «отката» от абстрактных баллов функциональности к более ощутимым строкам кода, но и как неплохая оценка уровня языков программирования.

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

В таком случае разумно воспользоваться эмпирическим способом нахождения оценки функциональности в баллах в зависимости от классификации вашего проекта. В основе этого способа лежат три классификатора – масштаба проекта, пользователей объекта проектирования и типа объекта проектирования (табл. 4).

Таблица 4. Классификатор проектов
Масштаб проекта, C1 Пользователи объекта проектирования, C2 Тип объекта проектирования, C3
Функция 1 Индивидуальное использование 1 Не требующий программирования (визуальная разработка и т. д.) 1
Объект 2 Потребители shareware ПО 2 Скрипт 2
Библиотека объектов 4 Академическая среда, инженерия 3 ПО встраиваемой одноплатной системы 5
Реализация концепции 5 Внутрикорпоративные, локальное использование 5 База данных 6
Прототип для последующего эволюционного развития 6 Внутрикорпоративные, распределенное использование 6 Клиент-серверное ПО 8
Приложение для внутренних нужд 8 Контрактный проект, гражданский заказчик 7 Математическое ПО 9
Приложение под заказ 9 Контрактный проект, заказчик – органы местной власти 8 Коммуникационное ПО 11
Приложение, пригодное к расширению функциональности в ходе жизненного цикла 10 Коммерческий проект 9 ПО управления процессами 12
Компонент внешней системы 11 Контрактный проект, государственное финансирование 14 ПО встраиваемой многоплатной системы 13
Новая масштабная система 12 Военный проект 15 ПО для общедоступных сервисов 15
Компонентная система 13  

Используя классификатор, вы можете получить оценочное значение сложности своего будущего проекта в баллах функциональности по незамысловатой формуле:

FP = (C1 + C2 + C3)2,35,

где FP – оценка в баллах функциональности, а Ci – соответствующие значения из таблицы. После этой процедуры воспользуйтесь методом «отката» и получите оценку сложности в строках кода.

Осталось, пожалуй, для демонстрации применить все вышесказанное «на практике». Предположим, что перед вами стоит задача разработать ПО для одноплатного компьютера, являющегося сердцем автономной системы охраны объектов. Система с вашим ПО будет выпускаться серийно и срок ее службы планируется весьма продолжительным. Последнее означает, что за период выпуска компьютера могут появиться новые типы датчиков и исполнительных устройств, и для обеспечения конкурентоспособности вашего изделия было бы неплохо обеспечить возможность дополнять ими функциональность уже произведенных изделий. Короче, масштаб вашего проекта – «приложение, пригодное к расширению функциональности в ходе жизненного цикла» (C1 = 10, табл. 4), это, очевидно, коммерческий проект (C2 = 9), объект проектирования которого – «ПО встраиваемой одноплатной системы» (C3 = 5). Сложность этого проекта в баллах функциональности:

FP = (10 + 9 + 5)2,35 = 1752.

Воспользуемся «откатом» и восстановим количество строк кода, необходимых для реализации проекта на языке C (самом распространенном при проектировании встраиваемых систем), для чего умножим значение FP на соответствующий коэффициент из табл. 3. Итак, ожидаемая сложность ПО – на уровне 262 тыс. строк. Ну а над полученным значением уже следует долго и много думать – стоит ли взваливать на себя обязательства и переходить к более детальному анализу проекта, выявлению функциональных требований и уточнению сложности с помощью калькулятора табл. 2.