Как разработчику оценить трудозатраты

author

Оценка проектов в IT — больная тема. Кто не давал невыполнимых обещаний, а потом не сидел овертайм, чтобы уложиться в тот срок, что сам и озвучил?

В начале пути, когда давал оценку будучи разработчиком, я постоянно недооценивал. Каждый раз выявлялась работа, которую я не учел. Коллеги советовали умножать оценки на 2, на 3, на число ПИ — но это не помогало улучшить точность оценок, а только добавляло других проблем. Например, когда нужно было объяснить, откуда взялась высокая оценка.

С того времени прошло 10 лет. За это время я участвовал в оценке более 200 проектов, набил много шишек и хочу поделиться с вами мыслями на тему оценки проектов.

Надеюсь, статья поможет вам улучшить качество оценок, которые вы даете.

Зачем давать оценки?

Процент «успешных» проектов не превышает 29% (Исследование The Standish Group за 2015 год). Остальные 71% либо провальные, либо вышли за рамки тройного ограничения (сроки, функционал, бюджет).

Из этой статистики делаем вывод, что оценка проектов часто не соответствует действительности. Значит ли это, что оценку давать нет смысла? На просторах интернета даже появилось движение за то, чтобы не давать никаких оценок, а просто писать код — и будь, что будет. Что успеем, то успеем (поищите по тегу #noestimates).

Не давать никаких оценок — звучит заманчиво, но давайте отвлечемся и представим, что вы заказываете такси. Вы спрашиваете водителя: «сколько стоит доехать до такой-то улицы», а он отвечает: «не знаю, садись в машину, доедем — скажу, сколько заплатить по приезду».

Или, например, вариант в стиле Agile: «Ну, мы будем ехать, а ты будешь платить мне каждые 10 минут в дороге — и так пока не кончатся деньги) Как кончатся — высажу, но, возможно, мы доедем, или будем уже рядом. Ну, а если не рядом, то это твои проблемы — не повезло.»

Примерно так ощущают себя заказчики в ИТ, когда им предлагают начать работы без каких-либо оценок.

В примере выше в идеале мы хотим получить от водителя точную цену, за которую он нас довезет. В крайнем случае, неплохо бы получить диапазон цен. Так мы сможем прикинуть — брать такси, ехать общественным транспортом, идти пешком или вообще никуда не ехать и остаться дома.

Лезть в машину, совсем не понимая, чего ожидать — не то решение, которое принимают в здравом уме.

Надеюсь, мне удалось убедить вас, что оценка — это важная составляющая для принятия решений на проекте. Она может быть близкой к реальности, а может быть не очень, но она нужна.

Причины недооценивания

Игнорирование теории вероятности

Давайте представим, что менеджер спрашивает разработчика, за сколько он сделает задачу. Разработчик уже делал подобное ранее и дает «наиболее вероятную» оценку. Пусть это будет 10 дней. Есть, конечно, вероятность, что задача займет 12 дней, но эта вероятность ниже, чем вероятность того, что задача займет 10 дней. Так же есть вероятность, что задача займет 8 дней, но и эта вероятность будет меньше.

Часто предполагается, что оценки на задачу/проект распределяются по нормальному закону распределения (подробнее о нормальном распределении). И, если изобразить распределение оценок и их вероятностей в виде графика, то мы получим следующую картину: Ось Х соответствует оценке, а ось Y -вероятности того, что эта оценка окажется верной, и задача займет именно этот срок (ни больше, ни меньше). В центре, как вы видите, — точка с наибольшей вероятностью или наиболее вероятная оценка. Эта вероятность соответствует нашей оценке в 10 дней.

Площадь под кривой дает суммарную вероятность в 100%. Получается, что если мы дадим наиболее вероятную оценку, то мы завершим проект/задачу в срок или ранее с вероятностью в 50% (площадь под графиком до оценки 10 часов — это половина площади фигуры, и равна 50%). Т.е., руководствуясь данным принципом и давая наиболее вероятную оценку мы должны срывать примерно 50% сроков.

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

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

Получается, что если взять «наиболее вероятную» оценку в 10 дней, то вероятность того, что задача будет готова в этот срок или раньше — меньше 50%.

Игнорирование текущего уровня неопределенности

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

Исследования Луиса Ларанхейра (PhD, Associate Professor at The University of Brasilia) также показывают, что точность оценки программного проекта зависит от степени проясненности требований (Luiz Laranjeira 1990). Чем более прояснены требования, тем точнее оценка. Оценка не точна, прежде всего, потому, что неопределенность заложена в самом проекте/задаче. Единственным способом сокращения неопределенности в оценке является сокращение ее в проекте/задаче.

В соответствии с этим исследованием и здравым смыслом, если мы будем сокращать неопределенность на проекте/задаче, будет увеличиваться и точность оценки. Данный график приведен для наглядности, и в реальности наиболее вероятная оценка может изменяться в процессе сокращения неопределенности.

Итак, основные причины недооценивания — это неопределенность и игнорирование теории вероятности.

Зависимость точности оценки от стадии проекта

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

Если взять оптимистичную, пессимистичную и наиболее вероятную оценки (оптимистичная оценка — это самый ранний срок сдачи из всех возможных, пессимистичная — самый поздний) и показать, как отношение между ними меняется со временем, от начала проекта до его завершения, то получится следующая картина: Эта фигура называется конусом неопределенности. Горизонтальная ось соответствует времени от начала работы над проектом до его завершения. На ней отмечены основные этапы проекта. На вертикальной оси отмечается относительная величина ошибки в оценке.

Так, на стадии исходной концепции наиболее вероятная оценка может отличаться от оптимистической в 4 раза. На стадии готового UI разброс оценки уже варьируется от 0,8 до 1,25 относительно наиболее вероятной оценки.

Для удобства привожу эти же данные в виде таблицы:

Этап жизненного цикла оптимистичная оценка пессимистичная оценка
Исходная концепция 0.25х
Бизнес требования (согласованное определение продукта) 0.5х
Функциональные и не функциональные требования 0.67х 1.5х
Интерфейс пользователя 0.8х 1.25х
Детально продумана реализация 0.9х 1.15х
Готовый продукт

Очень важная деталь — конус не сужается автоматически с течением времени. Для того, чтобы он сужался, нужно действительно управлять проектом и предпринимать конкретные действия, направленные на снижение неопределенности. Если вы целенаправленно не снижаете неопределенность по ходу выполнения проекта, то ваши дела будут выглядеть примерно так: Область выделенная голубым называется облаком неопределенности. На протяжении всего проекта оценка подвержена большим отклонениям вплоть до самого завершения работ.

Чтобы продвинуться по конусу в самую правую точку, где нет неопределенности, нам нужно создать готовый продукт :) Получается, пока продукт не готов, неопределенность есть всегда, и оценка не может быть точной на 100%. Но на точность оценки можно повлиять, снижая неопределенность. При этом, любое действие, направленное на снижение неопределенности, снижает разброс оценки.

Данную модель используют во многих компаниях, в том числе и в NASA. Некоторые адаптируют ее, чтобы учитывать нестабильность требований. Более детально об этом можно прочитать в «Software Estimation: Demystifying the Black Art».

Что считать хорошей оценкой?

Есть много версий ответа на этот вопрос, но на практике, если оценка отклоняется от цели проекта более чем на 20%, то у руководителя проекта нет пространства для маневра. Если оценка колеблется в пределах 20%, то проект можно завершить успешно за счет управления функциональностью, сроками, размером команды и другими параметрами. Это звучит достаточно разумно, поэтому давайте для примера остановимся на этом определении хорошей оценки (это решение должно быть принято на уровне организации — кто-то рискует, и их устраивает отклонение в 40-50%, а кому-то и 10% много).

Итак для нас хорошей оценкой будет считаться та, что отличается от фактического результата не более чем на 20%.

Практика. Оцениваем проект на разных стадиях

Давайте представим, что к вам пришел менеджер проекта и попросил оценить какую-то функцию или проект.

Первым делом нужно изучить доступные требования и понять, на каком этапе жизненного цикла находится описание задачи или проекта (Исходная концепция, Согласованное определение, Завершенные требования, Готов UI, Спроектирована архитектура).

Дальнейшие действия зависят от того, на каком этапе мы находимся:

Стадия 1. Исходная концепция

Если к вам приходит менеджер или клиент и спрашивает: «Сколько времени займет сделать приложение, где доктора будут консультировать пациентов?», то вы точно на этапе «Исходная концепция».

Когда имеет смысл давать оценку на данном этапе?

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

Что нужно, чтобы дать оценку на данном этапе?

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

Какие инструменты больше всего подходят на данном этапе?

  • Оценка по аналогии

Алгоритм оценки

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

Например, оценку можно озвучить как «Я не знаю сколько времени займет этот проект, так как данных недостаточно, но чем-то похожий на него проект Х занял Y времени. Чтобы дать хотя бы примерную оценку по данному проекту, нужно прояснить требования.»

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

Как перейти на следующий этап?

Для этого нужно прояснить требования, чтобы было понятно, зачем нужно приложение и какие функции оно будет выполнять.

В идеале нужно иметь навыки сбора и анализа требований.

Для того, чтобы повысить свои навыки в сборе и анализе требований, неплохо бы прочитать «Разработка требований к программному обеспечению» Карл И. Вигерс, Джой Битти

Для сбора первичных требований вы можете воспользоваться следующим опросником:

  • Для чего нужно приложение? Какие проблемы оно будет решать?
  • Какие типы пользователей будут пользоваться приложением? (для задачи, озвученной выше — это, скорее всего, Врач, Пациент, Администратор)
  • Какие проблемы каждый тип пользователей сможет решать в приложении?
  • На каких платформах будет работать приложение?

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

Стадия 2. Согласованное определение продукта

На данном этапе уже есть понимание, что приложение будет делать и что не будет. Хотя и без подробных деталей.

Когда имеет смысл давать оценку на данном этапе?

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

Что нужно, чтобы дать оценку на данном этапе?

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

Какие инструменты больше всего подходят на данном этапе?

  • Оценка по аналогии
  • Оценка сверху вниз

Алгоритм оценки

Если такой же проект уже делали, то можно сразу озвучить в качестве примерной оценки то время, которое ушло на тот проект.

Если данных по такому проекту нет, то нужно разбить проект на основные функциональные блоки, а затем каждый блок оценить по методу аналогии с блоками, которые делались на других проектах.

Так, например, в случае с приложением «где доктора будут консультировать пациентов» у нас могло бы получиться следующее:

  • Регистрация
  • Система записи на прием
  • Система уведомлений
  • Видео консультации
  • Система отзывов
  • Система оплаты

И для оценки блока «Регистрация» можно взять оценку с одного проекта, а для оценки блока «Система отзывов» — с другого.

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

Так, например, модуль «Система отзывов» может нам показаться в 2 раза сложнее модуля «Регистрация». Соответственно, для этого модуля мы можем взять оценку, в 2 раза превышающую оценку на модуль «Регистрация».

Этот метод (оценка одного блока относительно другого блока) очень не точный, и его лучше использовать, только если количество блоков, которые никогда не делались, не превышает 20% от блоков, по которым есть исторические данные. В противном случае, это будет гадание на кофейной гуще.

После этой процедуры оценку по всем блокам нужно сложить, и это будет наиболее вероятная оценка. Пессимистичную и оптимистичную оценки можно рассчитать, используя коэффициенты, которые соответствуют текущему этапу — х0,5 и х2 (см. таблицу коэффициентов).

В идеале, это уже можно озвучить менеджеру, он должен разобраться, что с этим делать.

Если же так случилось, что разобраться менеджер не может и просит одно число — есть способы дать и одно.

Как из 3-х оценок (пессимистичная, оптимистичная и наиболее вероятная) сделать одну, я расскажу позже в разделе «Как из 3-х оценок получить одну?».

Как перейти на следующий этап?

Чтобы перейти на следующий этап, нужно подготовить полный список требований. Есть много разных способов документирования, но мы рассмотрим распространенный вариант с User Story.

Для каждого блока нужно определить, кто им будет пользоваться и что конкретно будет делать там.

Так, например, для блока «Система отзывов» после сбора и анализа требований мы могли бы получить следующее:

  • Пациент может просмотреть все отзывы о выбранном докторе
  • Пациент может оставить отзыв доктору после видео консультации с ним
  • Доктор может видеть список отзывов, которые ему оставили пациенты
  • Доктор может написать комментарий к отзыву на свою консультацию
  • Администратор может видеть список всех отзывов на сайте
  • Администратор может редактировать выбранный отзыв на сайте
  • Администратор может удалять выбранный отзыв на сайте

Также нужно собрать и записать все не функциональные требования к проекту. Чтобы собрать их, можно воспользоваться следующим чек-листом:

  • На каких платформах должно работать?
  • Какие операционные системы нужно поддерживать?
  • С чем нужно интегрироваться?
  • Как быстро должно работать?
  • Сколько пользователей должно поддерживать одновременно?

Прояснение этого будет означать переход на следующий этап.

Стадия 3. Требования собраны и проанализированы

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

Когда имеет смысл давать оценку на данном этапе?

Когда нужно дать примерную оценку на проект перед стартом работы по модели T&M. Оценки задач с данного этапа могут быть использованы для приоритизации конкретных задач на проекте, для планирования даты релиза и бюджета всего проекта. Также их можно использовать для контроля производительности команды на проекте и оценке ее эффективности.

Что нужно, чтобы дать оценку на данном этапе?

  • Список функциональных требований
  • Список не функциональных требований

Какие инструменты больше всего подходят на данном этапе?

  • Оценка снизу вверх
  • Оценка по аналогии

Алгоритм оценки

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

Чтобы сделать это наилучшим образом, нужно представить все, что нужно сделать для реализации данной задачи. Можно мысленно, но лучше на бумажке.

Например, для нашей User Story «Пациент может просмотреть все отзывы о выбранном докторе» могла бы получиться следующая картина (иллюстрации ниже специально сделаны от руки, чтобы показать, как процесс оценки может выглядеть на практике): Тут мы разделили задачу на 3 составляющие:

  • Создать инфраструктуру в базе данных
  • Сделать уровень DAL, для выборки данных
  • Сделать UI, где будут выводится сами отзывы

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

Если вы хотите повысить свои навыки в проектировании интерфейсов, неплохо бы прочитать «Интерфейс» Джеф Раскин и «Об интерфейсе. Основы проектирования взаимодействия» Алан Купер.

Далее нужно представить, что именно будет делаться для каждой задачи и оценить, сколько времени это займет. На этом этапе нужно именно подсчитать время, а не угадать. Вы должны представлять себе, что вы будете делать для реализации каждой подзадачи.

Если есть задачи, которые занимают более 8 часов, их нужно разбить на подзадачи.

Оценку, которую вы получили после описанной процедуры, можно считать оптимистической, так как, скорее всего, она учитывает кратчайший путь из точки А в точку Б (при условии, что вы ничего не забыли).

Теперь самое время подумать о тех вещах, которые вы, возможно, пропустили, и скорректировать свою оценку. В таких случаях, как правило, помогает чек-лист. Вот пример такого листа:

  • Тестирование
  • Дизайн
  • Создание тестовых данных
  • Поддержка разных разрешений экрана

Один из возможных вариантов такого чек-листа вы можете посмотреть тут.

После прохода по этому списку нужно дополнить список задач тем, что, возможно было пропущено:

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

После того, как вы и это подсчитаете — ваша оценка, скорее всего, будет все ещё ближе к оптимистичной, чем к наиболее вероятной. Если посмотреть на конус, то эта оценка будет ближе к нижней его грани.

Исключение может быть в том случае, если вы уже делали подобную задачу ранее и можете точно утверждать, что знаете, как ее делать, и сколько времени она занимала ранее. В этом случае ваша оценка могла бы называться «наиболее вероятной» и соответствовала бы прямой 1х на конусе. В противном случае ваша оценка — оптимистичная.

Оставшиеся две оценки можно рассчитать, используя коэффициенты, которые соответствуют текущему этапу — х0,67 и х1,5 (см. таблицу коэффициентов).

Если подсчитать оценку и приведенного выше примера, мы получим следующее:

  • Оптимистическая оценка — 14 часов
  • Наиболее вероятная — 20 часов
  • Пессимистическая — 31 час

Как перейти на следующий этап?

Чтобы перейти на следующий этап, нужно спроектировать интерфейс пользователя. Лучшим способом сделать это будет создание wireframes.

Для этого есть множество программ, но я бы порекомендовал обратить внимание на Balsamiq и Axure RP.

Прототипирование — это отдельная обширная тема, которая выходит за рамки данной статьи.

Наличие wireframe будет означать переход на следующий этап.

Стадия 4. Интерфейс спроектирован

На данном этапе есть wireframe и полный список того, что может делать каждый пользователь в системе, а также есть список не функциональных требований.

Когда имеет смысл давать оценку на данном этапе?

Для подготовки точной оценки по модели Fixed Price, но также можно и для всего того, что было перечислено на прошлом этапе.

Что нужно, чтобы дать оценку на данном этапе?

  • Готовые wireframes
  • Список функциональных требований
  • Список не функциональных требований

Какие инструменты больше всего подходят на данном этапе?

  • Оценка снизу вверх
  • Оценка по аналогии

Алгоритм оценки

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

Как перейти на следующий этап?

Спроектировать всю архитектуру приложения и детально продумать будущую реализацию. Этот вариант мы рассматривать не будем, так как он довольно редко используется на практике. При этом алгоритм оценки после продумывания архитектуры не будет отличаться от алгоритма текущего этапа. Разница, опять же, будет в повышении точности.

Получаем из диапазона оценок одну

Если у вас уже есть наиболее вероятная, пессимистическая и оптимистическая оценки, то для того, чтобы получить одну оценку, можно использовать наработки Тома ДеМарко, который в своей книге «Вальсируя с медведями» поднял идею, что абсолютная вероятность может быть вычислена путём интегрирования площади под кривой (того самого графика асимметричного распределения вероятностей, что мы рисовали ранее). Оригинальный шаблон для подсчета можно скачать тут (также доступен без регистрации тут). В шаблон нужно просто подставить 3 числа и получить результат в виде списка оценок с соответствующими им вероятностями.

Например, для оценок 14, 20 и 31 мы получим следующий результат (скрин с шаблона excel):

Вы можете выбрать любую вероятность, которую посчитаете приемлемой для своей организации, но я бы советовал брать 85%.

Не знаем как оценить - говорим

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

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

Очень важно давать менеджеру эту информацию, иначе он может взять вашу оценку на веру, и даже не подозревать, что есть вероятность сорвать срок в 5 раз или вообще не сделать продукт на данной технологии / с данными требованиями.

Хороший менеджер всегда на вашей стороне, ведь вы в одной лодке, и его карьера зависит от того, уложитесь ли вы в срок, зачастую сильнее, чем ваша.

Сомневаемся - не обещаем

Многие организации и разработчики сами способствуют срыву собственных проектов только за счет того, что принимают на себя обязательства в слишком ранней точке конуса неопределенности. На ранней стадии, где возможный результат колеблется от 100% до 1600%, принимать решения и фиксировать сроки очень рискованно.

Эффективные организации и разработчики откладывают принятие на себя обязательств до того момента, как будет выполнена работа по сужению конуса.

Как правило, это характерно для организаций, находящихся на более зрелом уровне модели CMM, в которых процедуры сужения конуса явно описаны и соблюдаются.

Ниже приводится иллюстрация улучшения качества оценок в проектах ВВС США при переходе на более зрелый уровень CMM (Lawlis, Flowe and Thodahl,1995). Думаю, тут есть о чем задуматься. Статистика по другим компаниям подтверждает эту корреляцию.

При этом, точность оценки не достигается одними только методами оценки, она неразрывно связана с эффективностью управления проектами и зависит не только от разработчиков, но и от менеджеров проекта и высшего руководства компании.

Выводы

  • Дать оценку, которая совпадет с действительностью практически невозможно, но в ваших силах повлиять на диапазон, в котором она будет колебаться. Для этого нужно снижать неопределенность на проекте.
  • Дробление задач на составляющие поможет повысить точность вашей оценки. В процессе декомпозиции вы более детально продумаете, что будете делать и как.
  • Используйте чек листы, чтобы снизить вероятность что-нибудь пропустить при оценке.
  • Используйте конус неопределенности для того чтобы понять в каком диапазоне вероятнее всего будет колебаться ваша оценка
  • И напоследок — постоянно сравнивайте ту оценку, которую вы дали, со временем, которое реально ушло на задачу. Это поможет вам прокачать свой навык оценки, понять, что вы упустили, и использовать это в последующих оценках.

Полезные книги

На тему оценки трудозатрат очень много литературы, но я приведу 2 книги, которые просто обязаны быть прочитаны:

  • «Вальсируя с Медведями: управление рисками в проектах по разработке программного обеспечения» Том деМарко и Тимоти Листер
  • «Software Estimation: Demystifying the Black Art» Steve McConnell
Плюсануть
Отправить
Поделиться