Библиографическое описание:

Чугреев В. Л. Бережливая разработка программного обеспечения // Молодой ученый. — 2015. — №8. — С. 156-159.

Идея названия этой статьи позаимствована из книги «Бережливое производство программного обеспечения» [1], в ней авторы Мэри и Toм Поппендик сделали попытку перенести концепцию производственной системы Toyota (Toyota Production System — TPS) в область программных разработок. Тайити Оно (один из ее главных создателей) сформулировал семь видов потерь [2]: потери из-за перепроизводства; потери времени из-за ожидания; потери при ненужной транспортировке; потери из-за лишних этапов обработки; потери из-за лишних запасов; потери из-за ненужных перемещений; потери из-за выпуска дефектной продукции.

Суть TPS заключается в сокращении, ликвидации этих потерь. Программная разработка все же отличается от производства, поэтому Мэри и Toм Поппендик, опираясь на идеи Тайити Оно, Сигаэо Синго и др. специалистов в области бережливого производства, предложили свою концепцию. Своего рода проекцию TPS на программные разработки. Проекцию, несомненно, полезную, но все же имеющие некоторые недостатки и неудобства в плане применения.

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

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

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

1. Лишние функциональные возможности

«Только около 20 % функциональных возможностей в типичном пользовательском программном обеспечении используется регулярно, и около двух третей возможностей используется редко» (Джим Джонсон, председатель Standish Group) [1].

Наверное, каждый, кто пользовался программными пакетами типа Microsoft Office, согласится с вышеозвученным утверждением. Для примера читатель может оценить используемый лично им функционал, например, в текстовом редакторе Word. В лучшем случае это будут те самые 20 % от всех его возможностей. Если брать операционную систему Windows и все ее возможности по части настроек и оптимизации, то процент будет, скорее всего, меньше.

Основные причины появления лишнего функционала:

1)      Конкуренция между производителями программного обеспечения.

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

2)      Слабое понимание того, что действительно нужно потребителю, что будет востребовано, а что нет.

Вводя обширный функционал мы, по сути, пытаемся попасть в мишень потребительской ценности, стреляя длинными очередями. Мы пытаемся угадать ключевые потребности.

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

3)      Разработка по waterfall (каскадная модель).

Для каскадной модели характерны следующие фазы [3]:

1.                 Определение требований

2.                 Проектирование

3.                 Конструирование (также «реализация» либо «кодирование»)

4.                 Воплощение

5.                 Тестирование и отладка (также «верификация»)

6.                 Инсталляция

7.                 Поддержка

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

«Будьте так любезны, драгоценный заказчик, предоставьте нам список того, что программное обеспечение должно делать. И будьте добры расписаться внизу. После этого, если потребуется что-либо изменить или добавить, вам придется пройти через запутанный процесс, называемый “управление изменениями”, чтобы добиться одобрения каждого изменения. Поэтому, если вы хотите получить хорошее программное обеспечение, постарайтесь все предусмотреть заранее, поскольку нам нужно знать обо всем этом до начала процесса разработки.

Не удивительно, что наши заказчики включают в этот список все, что только можно. И очень часто меры, призванные ограничивать масштабы создаваемого программного обеспечения, дают противоположные результаты» [1].

Пути решения проблемы:

1)      Начать с малого.

Как отмечают Мэри и Toм Поппендик «целесообразно сначала полностью разработать 20 % программного кода, которые обеспечивали бы 80 % потребностей заказчика, и только после этого переходить к разработке следующих наиболее необходимых функциональных возможностей» [1].

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

2)      Убрать лишнее.

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

Это может быть сложно с психологической точки зрения. На написанный код уже потрачено время и силы, возможно, что кому-то когда-нибудь он все же пригодится. Выкидывать его просто жалко. Но при этом мы забываем, что его нужно поддерживать, его нужно учитывать при внесении изменений, он усложняет понимание программной системы. Поэтому если данные функциональные возможности необходимы условным 5 % пользователей, то от них можно и нужно избавляться, они «не делают погоду».

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

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

3)      Перейти на гибкую схему разработки.

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

Основные идеи (взяты из Agile-манифеста [4]):

-        люди и взаимодействие важнее процессов и инструментов;

-        работающий продукт важнее исчерпывающей документации;

-        сотрудничество с заказчиком важнее согласования условий контракта;

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

Однако нужно учитывать особенности организационной культуры заказчика, его готовность к насыщенному сотрудничеству с исполнителями. Также проблемой может быть неготовность заказчика отказаться от фиксированного бюджета и сроков проекта (для Agile характерна модель оплаты «Time & Materials»). В этом случае может помочь т. н. FFF-подход: Fix Time and Budget, Flex Scope — фиксированное время и бюджет, гибкие возможности [5].

2. Overengineering (избыточное проектирование)

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

«Избыточное проектирование заключается в том, что вы делаете код более гибким или сложным, чем он должен быть. Некоторые программисты делают это, поскольку полагают, что им известно, какие требования к разрабатываемой системе могут появиться в будущем. Поэтому они считают, что лучше сделать более гибкий и сложный проект уже сегодня, чтобы он без изменений соответствовал завтрашним нуждам. Это звучит разумно, если, конечно, вы обладает даром предвидеть будущее» [6].

Чаще всего такие «предсказания» несостоятельны, а заложенная в систему гибкость оборачивается ненужной тратой времени и сил. Более того, выбранное архитектурное решение приходится поддерживать в дальнейшем, затрачивая на это дополнительные ресурсы, отвлекая их от действительно нужного функционала. Усложненная кодовая база затрудняет чтение программы, а также мешает вносить в нее изменения.

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

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

3. Поиск и исправление ошибок

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

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

Основные причины ошибок:

1)      Нарушение технологии: принципов ООП, принципов написания чистого кода.

Примеры: большие классы (антипаттерн «God object»), большие методы, отсутствие единого подхода к именованию переменных и др. Все это естественным образом приводит к созданию хрупкого, запутанного, сложного кода, который, во-первых, способствует появлению ошибок, а во-вторых, затрудняет их поиск.

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

2)      Низкая квалификация работника, низкая культура кодирования.

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

3)      Неудачно выбранный инструментарий, технологическая платформа.

Можно привести пример с сильно и слабо типизированными языками, динамическая типизация — потенциальный источник ошибок, особенно для малоопытного программиста. Если есть выбор, то предпочтительнее язык с сильной типизацией. Также проверка ошибок на этапе компиляции предпочтительнее, чем их проверка в процессе исполнения. Если язык не компилируемый (типа PHP) желательно использовать IDE с поверкой кода во время его редактирования, например, PhpStorm.

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

 

Литература:

 

1.      Поппендик, М., Бережливое производство программного обеспечения: от идеи до прибыли [Текст]: пер. с англ. / М. Поппендик, Т. Поппендик — М.: Вильямс, 2010.

2.      Бережливое производство [Электронный ресурс]. — Режим доступа: https://ru.wikipedia.org/wiki/Бережливое_производство

3.      Каскадная модель [Электронный ресурс]. — Режим доступа: https://ru.wikipedia.org/wiki/Каскадная_модель

4.      Agile-манифест [Электронный ресурс]. — Режим доступа: http://agilemanifesto.org

5.      Getting real [Электронный ресурс]. — Режим доступа: https://gettingreal.37signals.com

6.      Кериевски, Д., Рефакторинг с использованием шаблонов [Текст]: пер. с англ. / Д. Кериевски — М.: Вильямс, 2008.

Обсуждение

Социальные комментарии Cackle