О пользе и вреде детального планирования

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


© see_another_side

Итак, что же хорошо в планировании (или плохо без него):

  • Понимание всего обьема и длительности работ;
  • понимание необходимых ресурсов и затрат;
  • понимание баланса между затратами и выгодой проекта и как результат — возможность отказаться от заранее невыгодных проектов;
  • возможность выбора оптимального пути выполнения проекта с помощью выполнения определенных задач параллельно и/или упрощение задач;
  • ощущение контроля над ситуацией.

Артефакты, на которых базируется каждый план: задача, ресурсы для выполнения, исполнители, длительность конкретной задачи, последовательность задач.

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

Посмотрим более пристально на артефакты:

Задача. Здесь имеется в виду детальное описание задачи в таком стиле: «Установка крепежа типа гвоздь в стену, на высоте 2 метра от пола в 20 см с левой стороны внутренней части входной двери». Готов утверждать что 90% задач страдают проблемой ястности в описании, особенно когда речь идет о более сложных абстракциях, чем «гвоздь» и «стена».

Ресурсы для выполнения. Это как правило материалы, и как следствие — их поставщики с их сроками, ценами, качеством и т.п.

Исполнители. Когда речь идет об точности и гарантированности такой форс мажор как «Человеческий фактор» всегда определяеться как самая нестабильная составляющая любого плана.

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

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

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

Проблемы, связанные с черезмерно детальным планированием:

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

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

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

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

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

Итак, если планы так плохи, то как же жить дальше?

Ответ прост и находится в мудрости веков. Например: «Богу — богово, кесарю — кесарево».

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

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

Другой интерестный вопрос — а как уговорить заказчика работать без плана? Здесь все же главный фактор — доверие. Если он вам доверяет — то достаточно и списка с ориентировочной суммой «итого». А если нет — то даже очень детальный план не поможет.

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

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

Когда люди строили первые хижины, они не начинали с плана, то же с автомобилями, самолетами и т.п. Или они отказались бы, посчитав, сколько все это стоит ? :-)

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

👍НравитсяПонравилось0
В избранноеВ избранном0
Подписаться на автора
LinkedIn



Підписуйтесь: Soundcloud | Google Podcast | YouTube

54 комментария

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.

Только одна причина, почему планы и планирование необходимы: планы менять легко, а начатое дело — трудно. Вносить коррективы имея план — легко, без плана — всё идёт в разнос. Имея план, имеем доверие между участниками, включая инвесторов. Не имея план — рождаем опасения и слухи.

Ценность плана в том, что его можно менять. Жёсткий план = плохой план. Любого руководителя, запрещающего возможность изменять план — считать врагом народа. Расстреливать не надо — лучше отдать конкуренту с лучшими рекомендациями. :)

Кто разбирается в рискменеджменте проектов, поддержите!

Совершенно согласен с статьей. Есть две причины, почему планы плохи.

1. Во всех проектах на моем опыте планы только замедляли и иногда значительно выполение работ. Мир динамичен. Т.е. непредсказуем. Т.е. на языке математики мы всё время получаем новую информацию. И где же, как не в программировании, это должно наиболее сильно проявляться? Мы работаем с информацией.
Простой тупой пример, недавно случившийся на работе. Решили сами для себя в проекте посмотреть на то, что будем показывать заказчику. Оно уже работает и решили увидеть как. И тут случается баг. Посмотреть, что в базе данных — минут 5-3. Баг вот он. Воспроизводится. Что говорит архитектор? «Мы только записываем баги, цель нашей встречи другая» (!!!!!!!!!!!) Извините, баг мы не могли предусмотреть. Его информационная ценность в десятки раз превышает план: посмотреть на картинки. Багов оценочно в том проекте до десятка. Нельзя терять такие моменты! Потеря информации, страшный урон. Потом это выльется или в потерю денег заказчиком или в гораздо большее время поиска и воспоризводства бага. Он ведь может и не воспроизвестись.

Да и просто простои по полдня, потому что один «запланировал» встречу на вечер, когда надо узнать буквально два-три вопроса — не более 10 минут. Мой колега неделю ждет встречи.

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

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

Отличный пример неоправданной индукции :)

Оговорюсь, все ниженаписанное я считаю справедливым для одного типа: fixed-all, в котором изменение в требованиях вызывает реэстимейт сроков и затрат заказчика.

Мир динамичен. Т.е. непредсказуем.

Не все работают на заказчиков, для которых fixed-all не включает в себя fixed requirements. В случае же, если требования жестко зафиксированы, то основная предпосылка для крупного срыва плана — нестабильность в архитектурных решениях, либо из-за ошибок в этой самой архитектуре, либо из-за того, что её решают менять по ходу (что, вообще-то говоря, может быть оправдано только в случае изменения требований). В обеих случаях за ошибку разработчиков платит заказчик. Если привести пример из жизни: представьте себе, что Вы заказали такси, но попросили предупредить, если она будет более, чем через 15 минут. Вам пообещали машину через 10 минут. Машина приехала через 25 и просит дополнительно плату за простой 15 минут, т.к. «добираться к вам далече и пробки в городе». Вот, собственно, так и видит ситуацию заказчик. Если развивать пример с такси, то прогнозируемость сроков — это не некая абстрактная сущность, это вполне себе численная метрика и в любом бизнесе эта метрика играет свою роль при выборе подрядчика (которым Вы, в данном случае, и являетесь); если Вы не можете назвать срок, в который работа с текущим объемом требований будет гарантированно закончена — у Вас нет конкурентного преимущества, а рынок разработки ПО намного более конкурентен, нежели кажется. Более того, если учесть в «цене» Вашего продукта не только прямые издержки, но и косвенные (например, упущенную прибыль от задержек внедрения), то цена эта возрастет ещё сильнее. А рынок разработки ПО, между прочим, отличается эластичностью по спросу выше единицы.

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

Логичное решение, между прочим. Собрались люди обсудить демо. Демо в каком-то моменте ломается, при этом поломка воспроизводима (т.е. подразумевается, что steps to reproduce вполне ясны). Если эта ошибка — showstopper, т.е. мешает обсудить и показать остальные части демо — все, расходимся, чиним. Если же нет — заканчиваем разговор о том, что показать/обсудить можно и идем чинить.

Планирование просто враг программирования и проектирования.

Здесь и далее по тексту пункта 2 Вы смешиваете две несколько несмешиваемых вещи: планирование и архитектуру. По поводу планирования и аналогий на его тему в программировании — попробуйте, как-нибудь, интересу ради, написать метод, в которой нужно оперировать объемом памяти, большим, нежели доступен в системе в целом: что Вы выберете для управления памятью — ручной вызов деструкторов или сборщик мусора, взлетающий по одному ему ведомому расписанию?

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

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

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

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

Напоследок — занятное наблюдение: многие из тех, кто являются ярыми противниками детального планирования, считают, что создание ПО — «is an art». Так вот, «programming art’а» в большинстве нынешних проектах — не более, чем в сборке машин на конвейере: проектов высокой алгоритмической сложности и новизны в нынешнем IT явно не 99%, наоборот, хорошо, если 1% наберется; ещё процента 3% накинем на значительную адаптацию неких общих алгоритмов к предметной области и на проекты, требующие максимальных оптимизаций по ресурсам из-за ограничений целевой платформы. Все остальное — вполне укладывается в рамки manufacturing или craft — т.е. обычного производства. И никаких причин не применять к этой сфере деятельности традиционные для производств практики, за исключением человеческого желания выделиться, нет и особо быть не может.


Логичное решение, между прочим. Собрались люди обсудить демо.
Нелогичное. Каждый баг имеет высокую информационную ценность. А не эго собравшихся. Они собрались пофапать на картинки? Сори за грубое сравнение. Собиралось трое человек. Один — не разработчик. Но я думаю, и 5-8 человек — логика та же. Баг важнее. Баг потому и баг, что причина его не известна. Значит и воспроизведение под огромным вопросом. Посмотреть причину было делом трех минут. Кстати, я настоял и мы так и сделали. Но я о том, что не все понимают важность быстрой рекции на изменяющуюся ситуацию. Случилась редкая и удивительная вещь. Был не баг, а недостаток требований. А это еще бОльшие проблемы и деньги. И то, насколько быстро мы отреагируем, настолько и сэкономим. Поиск такого бага «потом» сулит побольше работы.

Да, извините, в первом сообщении не точно выразился. Баг во время демо видели, но не воспроизводили. Архитектор начал заисывать в блокнот, что есть такой баг. И даже забывал условия записать (идентификаторы и т.д.). Чтобы оставлять на потом или отдавать разработчикам чинить баг, желательно добиться хотя бы воспроизведения. А лучше прямо сейчас, если возможно, и чинить.


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

— дальнейшая интеграция того, что пишете Вы и Ваша команда в свои решения, причем не только на уровне «подключаемой отдельной библиотеки», но и в ключе «а вот сейчас мы берем этот конкретный код».
— развитие заказного продукта, но уже не Вашими силами.
— ранняя подготовка к приемочному тестированию: знание о внутренней структуре разрабатываемого объекта позволяет провести куда более полезные тесты, нежели чистый блэкбокс и сильно снижает риски «написания так, чтобы тесты проходились»
Никакие кишки и в этом случае не нужны. Если на уровне библиотеки — только интерфейсы. Если заказчику нужен код, то у него есть код. ЮМЛ-диаграммы классов только самые поверхностные, чтобы суть передать. И чем меньше этого нужно, тем лучше. Заказчик хочет развивать продукт? Так с чего вдруг он не сможет разобраться в коде? Домохозяйкам и сантехникам ЮМЛ-диаграммы может быть понятнее кода и для красивее выглядят. Но они одинаково как и код для них бесполезны — профита не будет. Тот, кто развивает продукт, должен уметь читать и код.

Кроме того, наличие плана разработки минимизируют возможность ситуации (условно)"нам надоел этот фреймворк, давайте перепишем на другом, он моднее/удобнее нам" — вот, собственно, тот случай, когда заказчику кишки вроде бы и не нужны, но дополнительным стимулом выступают — решили что-то сделать вне плана — удачи, все дополнительные эксперименты, к сожалению, не оплачиваются.
Функцию не отхода в сторону берут на себя use cases. От заказчика. А чтобы не фантазировали на счет фреймворков, нужны объективные правила и способы обоснования своих действий. Например, эволюционное проектирование. Это в предварительном проектировании выбирают, основываясь только на «хочу» или «кажется» или «красиво». При эволюционном проектировании будет требоваться обоснование. Не для заказчика, а для самих разработчиков.
Тут просто надо иметь определенные навыки и следовать правилам, тогда это работает. Эволюционное проектирование — это проектирование по мере развития проекта. Это ТДД и рефакторинг. Таким образом проект всегда находится в состоянии, когда его можно немного переделать. А в предварительном проектировании ТДД и рефакторинг практически не проводятся. Рефакторинг же может перевернуть архитектуру так, что она не будет соответствовать запланированной. И вот, в предварительном проектировании часто и случаются ситуации, когда «надоело» и «хочется с нуля переписать».

Напоследок — занятное наблюдение: многие из тех, кто являются ярыми противниками детального планирования, считают, что создание ПО — «is an art»
Честно говоря, я не считаю программирование искусством. Но понимаю, почему так говорят. Всё перевернули с ног наголову, чисто формально. У людей, которые предварительно проектируют, есть впечатление, что они делают что-то монументальное, сложное и большое, поэтому занимаются предварительными расчетами. Люди, которые пошли в опозицию, заявили, что расчеты — плохо, это искусство уметь проектировать «на гребне волны».
Но на самом деле, всё ровно наоборот. Откладывать проектирование до последнего, изменять код, как только что-то изменилось в требованиях, в багах или еще чем-то — это чистая рутина, основанная на четких правилах. Объективных правилах. Люди в момент таких изменений оценивают код и архитектуру рядом параметров. И даже если они знают, что через пару дней им нужно будет какой-то функционал — не пишется, потому что оценка происходит только «на сейчас». Принцип YAGNI. Оценка кода, оценка паттернов — всё механическое. Рефакторинг — почти механический.
А вот, люди, которые воображают, что они расчитывают что-то — не пользуются никакими объективными правилами. Кроме ощущений «это более красивое решение», «это более гибкое решение» (а кто сказал? Любая гибкость — гибкость только в предсказанных направлениях, но жесткость в других), или «нам кажется что это будет работать». Кстати, последнее утверждение чаще всего правильное, но мало ли что можно заставить работать. Вопрос — как, сколько багов, насколько надежно и сколько времени потратится.
Так где артисты тогда? :)

Обычно в реальности цифры получаются в ключе «через четыре месяца лучше, чем неизвестно сколько — месяц или полгода».
Ну вот я (и не только я), поддаю сомнению, что лучше 4 месяца. На самом деле в моем опыте разрывы и гораздо больше бывают. Что интересно, так то, что планирование — это такой самообман, когда есть некая вера в то, что есть план и ему возможно следовать. Сроки в предварительно планируемых проектах срываются еще больше. Закладывают на всякий случай время в полтора/два раза больше — и то время проедается. А перед дедлайнами всё пишется авралом, архитектура меняется, прямо как в эволюционном проектировании. Только без тестов и оценок.

Нелогичное. Каждый баг имеет высокую информационную ценность.

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

недостаток требований

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

Это оптимизация? Чтобы писать оптимальные программы, нужно не оптимизировать. Оптимизация как раз всегда делается после того, как код написан. Принцип известен, как избегание преждевременной оптимизации.

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

Никакие кишки и в этом случае не нужны. Если на уровне библиотеки — только интерфейсы.

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

И вот, в предварительном проектировании часто и случаются ситуации, когда «надоело» и «хочется с нуля переписать».

И я по-прежнему не понимаю, почему заказчик должен платить за провтыки на этапе проектирования? Есть зафиксированные требования к тому, что должно быть предоставлено, есть конечный срок, когда это должно быть предоставлено — почему этот срок должен быть сдвинут из-за того, что на этапе проектирования, собственно, проектированию не было уделено достаточно внимания?

это искусство уметь проектировать «на гребне волны».

Один вопрос (в двух частях) только: почему 99% проектов, которыми заняты апологеты проектирования на гребне волны с технической точки зрения выглядят, как обертка вокруг какого-либо крупного фрейворка — рельсов, спринга/хибернейта, аспнета, т.е. там, где заведомо запороть архитектурой решения проект довольно сложно? И почему, например, большинство хардверно-софтверных компаний (в которых пишется, например, ПО под телефон, не «Энгри бердс», а те же прошивки) реализуют чуть ли не чистый вотерфолл в качестве модели жизненного цикла?

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

:устало: ну да, ну да. Навыки человечества по управлению проектами, идущие чуть ли не с Древнего Рима, куча работ по Software development effort estimation, созданных на основе реальных проектов — это все воображение. Объективных правил, которые можно установить и которые действительно улучшают ситуацию на проекте — предостаточно, другое дело, что применять их на проекте длиной в два-три человекомесяца — стрельба из пушки по воробьям, но мы же не обобщаем, правда?

Сроки в предварительно планируемых проектах срываются еще больше.

dou.ua/...ovaniya/#196731 — вот ровно в этом комменте (в п.1) я написал про одну из двух основных причин, почему срываются сроки fixed-all предварительно планируемых проектов — исполнитель понимает, что он это сможет сделать за год, но знает, что заказчика срок больше 6 месяцев не устроит — и желание кушать заставляет принимать предложение и в дальнейшем тянуть волынку. Вторая причина — банальное незнание — незнание скорости работы своей команды, незнание особенностей выбранных технологий: нет, серьезно — я наблюдал, как люди подписывались на проект на Ruby и декларировали какие-то планы и сроки, при том, что реально в команде не было ни единого рубиста и первым делом они планировали «месяц учить язык».

Только вот обобщать опять же не стоит

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

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

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

Это работа в заведомо ограниченном по ресурсам операционном окружении, причем ограничения эти таковы, что недостаточно кучерявое решение не «будет работать плохо», а просто не взлетит — и таких задач валом: посмотрите, например, на большинство задач, связанных с эмбеддедом разного рода.
Ничего страшного, что в заведомо. Задачи такие бывают. Но это не значит, что сразу на выходе оно должно летать. Не должно. Еще и наказать за полеты надобно ))
Я занимался разработкой СУБД. Когда очень жесткие требования были по производительности.
Кнута и надо дословно понимать. И кодить в первой итерации — не в смысле г-окодить, а выражать прямо мысль, без хитростей. Архитектура должна быть проста и очевидна.

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

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

А я и не утверждал обратное. Иногда надо. Но тогда ЮМЛ-диаграмы должны быть не подробными, а выражать только суть. С описанием. По каждому пункту. Но заметьте, это совершенно другое, чем использовать диаграммы «до кодирования», чтобы распланировать «что кодировать». У диаграмм есть один недостаток — они практически никогда не соотвествуют дейтствительности. Код не врет. Код — единственный первоисточник. И есть разница — сначала рисовать диаграммы, а потом по ним кодить, или сначала кодить, а потом рисовать диаграммы. Когда проект завершается, то как раз время сделать снимок того, что получилось. Тогда диаграммы меньше устаревают. Диаграммы можно делать и при обсуждении, что будем кодировать. Но очень общие. И такие диаграммы выбрасываются.

И почему, например, большинство хардверно-софтверных компаний (в которых пишется, например, ПО под телефон, не «Энгри бердс», а те же прошивки) реализуют чуть ли не чистый вотерфолл в качестве модели жизненного цикла?
Да проще простого. Потому, почему и в большинстве контор у нас. Люди ленивы и тяжело учатся. Обучение так происходит: сначала учат циклы и ветвления. Потом ООП. Потом добираются до паттернов. При этом даются готовые решения. Потом примеры решений. Иначе не научишься. И у людей формируется мышление — что решать надо сразу. Стоило бы и дальше учиться, но у нас уже если человек это знает — синьор.
Каждый раз при дедлайне какая-то ерунда происходит, каждый раз г-окодят и каждый раз после этого делают вывод: «наверное мы плохо планировали». При этом, что интересно — 80 процентов кода или переделок приходится на последних два дня перед дедлайном. Это значит, что когда перестают обращать внимание на план, когда реально задница случается и все в едином порыве готовы делать всё для единой цели — эффективность повышается в разы. Правда она получается вместе с г-окогод: «насяльника, я починил».

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

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

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

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

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

А я и не утверждал обратное. Иногда надо. Но тогда ЮМЛ-диаграмы должны быть не подробными, а выражать только суть. С описанием. По каждому пункту. Но заметьте, это совершенно другое, чем использовать диаграммы «до кодирования», чтобы распланировать «что кодировать».

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

Да проще простого. Потому, почему и в большинстве контор у нас. Люди ленивы и тяжело учатся.

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

Для избежания такого существует стадия анализа требований. И исходя из этих требований ведется вся остальная деятельность. Если требования не сформулированы в виде «сделайте нам хорошо»
С требованиями всё нормально было. Анализ большой и крупный — это если в водопаде. Но и так анализ был. Анализ не для избежания, а для уменьшения вероятности. Избежать всего нельзя. В общем, в нашем случае случилась такая беда. В нашем проекте, довольно крупном, есть даже DSL. Гибкий язык программирования для аналитиков, которые настраивают систему. Конечно, т.к. настройки могут быть очень гибкие (но с типобезопасностью и проверкой, чтобы система не обрушилась), то и поведение системы стало не совсем очевидным. В этой системе делаем дополнительный функционал, который называем проектом. И вдруг, во время демо появляется неожиданное поведение, которое выглядит как баг. Люди другого ожидают. Выясняется, что не баг, а настройка. Причем вполне и правильно сделанная. Но в требованиях для именно этого проекта не учли, что и такое возможно. И стал вопрос, какое поведение нашего проекта считать верным.

Это всё плохо, DSL-и и всё такое. Система стала сложная. Но бизнесу нравится. Аналитики совсем не дураки, которые языком пользуются. Хотя энтропия растет. Но надо, так надо.

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

Что делать в том случае, если выражение мысли без хитрости получается заведомо неудовлетворительным в ключе производительности, устойчивости или потребления ресурсов?
Делать заведомо неудовлетворительное, но прямое выражение мысли. Непрямое — успеете. Когда вы делаете непрямое сразу — вы угадываете. Когда вы делаете прямое, а потом замеряете — вы на правильном пути. Есть два варианта проектов. Если проект — просто бизнес-приложение, то вообще никаких вопросов — делаете прямое отражение мыслей, предметной области и т.д. Потом оптимизируете. Другой тип приложений — это тот, который требует сложных алгоритмов, а не отражения сущностей предметной области (хотя если они есть, следуете первому варианту). Если нужны алгоритмы, то просто из нескольких выбирается лучший. Они обычно все уже есть. Нужно только изучить опыт. Далее оценить сложность алгоритмов. Далее возможно реализовать несколько. Сам алгоритм может не давать высокой производительности сразу. После этого следуют стандартные шаги оптимизации — замеры, выбор узкого места, оптимизация. Есть и способы оптимизации, опять же стандартные. Вынос за пределы цикла, кэширование и т.д. Но все эти шаги возможны, когда у вас есть код. Оптимизация — это процесс. И оптимизировать нужно что-то, что уже есть в наличии.
Я вообще с трудом понимаю, почему большинство программистов в критерии оценки кода вносят его производительность (производительность в первом выходе кода). Это какая-то религия, что-ли. Почему-то считают как за большую заслугу сделать сразу код, который будет «быстро» выполняться или меньше памяти есть. А то, что код г..о, нечитаемый и неподдающийся дальнейшим изменениям и сопровождению — уходит даже не на второй план.
Кстати, я пришел на проект, который давно создавался. И он был очень неоптимальным. А смех в том, что человек, который его писал, пытался его сделать оптимальным. Когда я тонны г..окода просто выбросил и проект начал более прямо выражать мысль — он намного легче начал дышать и лучше работать.

Еще не идеал, но производительнее где-то на порядок.

Подозреваю, что в каком-то смысле я или Вы смешали в дискуссии два разных плана — тот, который необходим заказчику (внешнему или внутреннему) и тот, который пытается составить руководитель группы для своей дальнейшей работы.
Да, я о вторых, которые не нужны. Т.е. если вторые нужны, то только в самом общем виде, чтобы отразить суть следующей работы. Иначе, если диаграммы подробные — то пусть и кодит руководитель. Работа уже сделана. С первыми то же самое. Если заказчику нужно понять суть работы программы с т.з. определенных вопросов — то по ним и составляются диаграммы, отражающие суть. Но не глубже. Для «глубже» есть код.

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

Именно поэтому в подобных компаниях с одной стороны легче согласовать проект с ощутимым запасом времени, но с четко зафиксированной конечной датой, в которую заложены обозримые риски
Я пытаюсь рассказать только свой опыт. Правда, я почти всегда в более менее итерационных процессах участвовал и аджайл. Сравнивать могу, т.к. кодил не на острове — в компаниях часто паралельно случаются водопады. Тут больше религия, тяжело сказать без замеров. Но личное ощущение в том, что вообще нет никакого выиграша в планировании. Сроки срываются и там и там. Но при планировании как раз сроки срываются гораздо сильнее. И это не зависит от запаса времени. Хоть в 4-ре раза взять запас. Он сорвется. В аджайле точно так же берут время на проект «на глаз», умножить на два. Точно так же могут прикинуть до старта проекта, удастся его завершить за полгода или нет. Также и в водопаде. Но суть в том, что в аджайле гораздо вероятнее закончат через полгода, чем при водопаде. А может на два месяца и раньше. В водопаде возьмут полгода, закончат может быть через год. А суть простая — распределение времени. Когда люди не планируют каждый час — то они гибко к работе относятся. Например, мы участвуем в проекте. Мы обсудили, что мы хотим и очень приблизительно как. Я имею ряд задач, отсортированных по приоритету. И тут мне нужно общение с колегой. Но так случилось, что он занят. При планировании наперед — всё, затык. Поток работы остановлен. Я должен предупредить колегу, он перепланирует свои дни. А может нужно общий план изменить. Схемы перерисовать.

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

Они обычно все уже есть. Нужно только изучить опыт. Далее оценить сложность алгоритмов.

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

Я вообще с трудом понимаю, почему большинство программистов в критерии оценки кода вносят его производительность

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

Тут больше религия, тяжело сказать без замеров. Но личное ощущение в том, что вообще нет никакого выиграша в планировании.

На самом деле, тут скорее вопрос в применимости тех или иных практик на те или иные типы проектов. Вотерфоллы — это ещё, кстати, не самое страшное; когда на команду из четырех человек и проект на полгода пытаются натянуть плохопонятый RUP — вот где радость сокрыта-то. Единственное большое «но» заключается, собственно говоря, в том, что порой в детально распланированных проектах распространен подход «кто на поезд опоздал — нефиг торопиться», т.е. если уж сроки с некоторой ненулевой вероятностью сорваны, то так оно и будет. Но тут уже вступает в силу вопрос мотивации исполнителя — иными словами, убытки заказчика от задержек тем или иным образом должны трассироваться на исполнителя.

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

В вопросах микроменеджмента я с Вами согласен, хотя в принципе не вижу проблемы в том, чтобы иметь глобальный план реализации, например, функциональных требований (не конкретной таски, а «фичи», которая может включать в себя десятки и сотни тасков разной степени приоритетности). В подобном подходе есть только один минус — при достаточно больших командах (обычно — от 10-15 человек в рамках одного модуля) и ощутимом разбросе уровня навыков/знаний внутри команды могут возникнуть ситуации, когда тот, от кого ВСЕМ нужны ответы, причем разлогие, не имеет на это времени, либо же возникает подобие дэдлока, когда по двум связанным задачам одновременно нужен ответ двум людям друг от друга и ни один из них до получения ответа не может продолжать работу;соответственно, нужно вводить механизмы их разруливания, обычно в виде каких-либо точек синхронизации.

Лично я могу это объяснить тем, что есть ряд задач, в которых производительность дает больше итоговой выгоды, нежели экономия на времени дальнейшего рефакторинга/расширения. Не во всех проектах есть необходимость в постоянных доработках и расширениях.
Пытаюсь объяснить только одну вещь: оптимизация до написания кода ведет неоптимальным решениям. Т.е. если производительность действительно важна, то тем более ни в коем случае зараннее не оптимизировать. В случае алгоритмов и чужого опыта, который нужно изучить зараннее — это относится вообще к любому проекту. Если есть стандартные решения и чужой опыт, то его желательно знать. Потом, даже очень сложные алгоритмы требуют не очень много кода. И как раз их не выбирают просто раз и на весь проект. Так выбрать можно, если есть чужой опыт и уже есть сравнительная информация (но не всегда верить надо, а лучше проверить). Создают несколько алгоритмов. Делают замеры и вылизывают производительность.
Но и циклиться на алгоритмах не стоит. Обычно проект состоит не просто из одного алгоритма. И не так уж и давят на нас тяжелые выборы алгоритмов. Сортировка? Или пробежаться по графу? Всё это давно решено и тривиально. Если проект — не просто один алгоритм, а есть какие-то use-cases, что должен пользователь делать, то в местах, где алгоритмы должны быть, либо самый простой, либо вообще тупой перебор (если это приводит к решению за конечное разумное время). Если же проект на грани возможного и невозможного и неясно, дадут ли приемлемую производительность алгоритмы — тогда делается прототип. На котором гоняют алгоритмы до уверенности, что будет работать. Но опять же, после создания прототипа, делаются на нем замеры и улучшается производительность. Но не до.
Без замеров нет оптимизации как процесса. Кнут, вообще-то, как раз специалист в алгоритмах и производительности. И не зря он самым бОльшим злом считает преждевременную оптимизацию. Чтобы оптимизировать нужно иметь цифры.
Важность производительности программных продуктов сильно переоценена. Дело в том, что «тормоза» возникают обычно в циклах. При разовых операциях не возникают. Пользователю глубоко по барабану, 2 миллисекунды отрабатывает нажатие на кнопку или 70. Вот, по выходу готового продукта делают замеры и сильно удивляются, что на самом деле мест, которые тормозят — 1-2. И не там, где ожидали. Остается вылизать внутренние циклы. Или может быть и подобрать другой алгоритм. Все же программисты, которые никогда не участвовали в проектах с жесткими требованиями по оптимальности, делают как раз наоборот. Оптимизируют всё подряд. Передачу в метод параметров. Дублируют данные. Когда спрашиваю «зачем?», говорят, быстрее будет работать. Это сострадание к процессору?

Это всё какая-то мода и психология. Скучно, наверное, программистам.

Пользователю глубоко по барабану, 2 миллисекунды отрабатывает нажатие на кнопку или 70.

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

Всё это давно решено и тривиально.

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

А если вы, например, пишете библиотеку, выполняющую вычислительные операции (например, создает хэш некоторых входных данных), то просадка за счет единичных операций может быть значительна, потому что все циклы за Вас создадут уже те, кто будет эту библиотеку использовать.
Тут два взаимодополняющих ответа.
1. Часто ли вы пишете библиотеки на продажу?
Точно так же, как и часто мы пишем ПО для космических кораблей или майкрософт-офис.
2. Логика точно та же. Оптимальное приложение получается только и только тогда, если первый код пишут прямым, а не оптимальным. А оптимизации проводятся как результат замеров. Возможно, вам придется больше паблик интерфейсов тестировать. Но логика та же: когда вы сразу пишете «оптимальный код» — вы пишете не оптимальный код, который невозможно будет оптимизировать потом. Потому что есть разница между глобальным минимумом и локальным. Нет никакого толку выиграть стоимость спичечного коробка, но проиграть миллион. И это не просто метафора. Если поучаствовать в таких проектах по такой методике, вы поразитесь насколько бывает неожиданной разница. В проектах с жесткими требованиями к производительности не размениваются на копейки. Например, те кто не участвовал в оптимизациях — очень радуются, когда выигрывают производительность в полтора-два раза. А в проектах с жесткими требованиями работодатель может сказать, что хочет в сто раз. Или тысяча. И часто это сделать реально. Почему? Не потому что глупости пишут изначально. А потому что есть разные факторы, влияющие на производительность. И они известны и отсортированы по важности. Те, которые более важны, могут в сотни раз или даже тысячи изменять производительность. Второй ньюанс в производительности, это то, что производительность каждого отдельного участка кода — это сумма факторов. И степень влияния каждого фактора предугадать тяжело. И не нужно. Это признак плохого программиста. Кстати, Макконел в книге «Совершенный код» говорит, что стремление оптимизировать наперед — признак вечного студента.
И он чертовски прав, даже для нашей страны. Наихудшие программисты, которые писали самое страшное и супер неоптимальное ПО на моей памяти — те, кто участвовали в студенческих олимпиадах по программированию. К сожалению, наше образование портит людей. А неоптимальное и страшное оно как раз было потому, что люди явно страдают предварительной оптимизацией. И их предположения про работу компилятора или базы данных бывают настолько наивными...

Вот, простой пример из практики. Нам нужно сделать оптимальный алгоритм работы с данными. Есть два или три известных алгоритма. При этом сложность алгоритмов разная. Одни там, допустим квадратичные, вторые логарифмические (или линейные, не важно). Но квадратичный оказывается на данных, которые нужны в проекте, обгоняет другие, когда количество итераций меньше тысячи. Это можно узнать только после замеров. Тогда решается — мы реализовываем два. Но перед началом работы, проверяем количество нужных итераций. Вот это я думаю — культура программирования. Я из некоторых колег не могу выбить оценочное мировоззрение, что «г..нокод» — это не то, что сразу не оптимальное, а то, что сразу оптимальное, но непростое и нечитаемое. Просто шкала ценностей такая — человек столкнулся с первым выходом кода, который работает, но медленно, но писал другой человек — и он называет это г..нокодом. Для оптимизации есть своя фаза. Как раз оптимизации делают из кода г..нокод. И лучше, чтобы это произошло как можно позже. Когда код отлажен и работает правильно и не планируется вносить много изменений.

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

В зависимости, что более важно в проекте, так и делают проект. Если же уверенность есть, что почти любое решение работать будет, но не любое устроит — то можно писать даже вместо алгоритмов сразу заглушки. А потом поиграетесь в выбор нужного алгоритма.

Но не нужно просто думать, что если вы пишете сразу неотимальное и даже неприемлемое решение, то вы поступаете плохо и у вас никаких шансов и вы увеличиваете объем работ (потом надо будет переделывать на оптимальное). Вы уменьшаете количество работ. Вы стремитесь таким образом к наиболее оптимальному решению — глобальному. Не нужно экономить на спичках, но терять всё остальное. Нормальные люди вас не осудят, если оно сразу не работает быстро. А вообще, надо бы и наказывать за оптимальные решения сразу. Даже если вы угадали (поверьте, это очень редко бывает даже у опытных в оптимизациях людей), то вы нарушили последовательность работ. Что значит тогда оптимальное? Когда вы говорите, что сделали оптимальное решение — то это ничего не значит, всё относительно. Когда вы говорите, что провели замеры и ваше решение выбрано из ряда, в котором, по сравнению с первым производительность выше в 15 раз, со вторым в 3 раза и т.д. — это уже какое-то обоснование.

Тут два взаимодополняющих ответа.
1. Часто ли вы пишете библиотеки на продажу?

Точно так же, как и часто мы пишем ПО для космических кораблей или майкрософт-офис.

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

Оптимальное приложение получается только и только тогда, если первый код пишут прямым

Что такое «прямой код»? Если под этим понимается «код, реализующий заявленные требования, при этом написанный без использования заведомо неоптимальных конструкций и не содержащий нетривиальных конструкций, целью которых является оптимизация под конкретную целевую платформу», то этот код я бы счел для первого раза как раз оптимальным. Фокус в том, что зачастую, на этапе прототипирования есть смысл создать именно proof-of-concept, т.е. нечто, что в целом реализует заявленный функционал, но после подлежит не рефакторингу, а выбросу и созданию наново, учитывая полученные от создания прототипа знания.

оптимальное, но непростое и нечитаемое.

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

Что такое «прямой код»? Если под этим понимается «код, реализующий заявленные требования, при этом написанный без использования заведомо неоптимальных конструкций и не содержащий нетривиальных конструкций, целью которых является оптимизация под конкретную целевую платформу», то этот код я бы счел для первого раза как раз оптимальным.
Прямой код — код, который четко и прямо выражающий мысль с т.з. цели заказчика. Т.е. вообще без никаких оценок отпимальности и не связан с реализациями. Т.е. ни заведомо неоптимальный, ни заведомо оптимальный. Языки программирования позволяют, если потренироваться — выражать мысль, а не конструкцию. Например. Если надо перебрать все элементы, то используют foreach, а не for. Последний уже завязан на порядок обхода. А сама суть того, что вы хотите сделать — не связана с порядком. Второй пример, выделение и освобождение памяти — никак не связаны с тем, что нужно, это уже фокусы реализации и возможно языка. Всё это при первом решении нужно как можно больше сводить к минимуму. План прост, поэтому красив ))
Если вам нужна сумма и вдруг есть у коллекции метод Sum(), то он предпочтительнее, чем писать цикл и суммировать. Потому что вы хотите сумму, вам нужна сумма, но никак в требованиях нет, каким вы образом ее получаете.

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

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

И далее. Сделать хеш-таблицу и выбрать цепочки или прямую адресацию — не связано с задачей — это плохо. Почему? Я сомневаюсь, что Ваш проект связан с тем, чтобы придумать новый алгоритм для хеш-таблиц и подарить миру. Мало что здесь можно придумать. Думаю, он у вас не цель, он средство. А проект состоит далеко не из только алгоритма работы хешами и быстрого поиска. Поэтому плохо то, что Вы тратите на это свое время. Не отрицаю, что это в конечном итоге может понадобиться. Но предлагаю в том месте, где Вы это делаете, сразу заменять на стандартные уже кем-то созданные структуры данных. Те же хеш-таблицы из каких-то библиотек. Как только будет проект собран, можно уже тестировать кирпичики. И возможно потом поискать более оптимальное решение.

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

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

Память ничем особо не отличается от любого другого доступного ресурса, в общем-то, за исключением того, что (на первый взгляд) с ней вообще проще — в отличии от ресурсов процессора, её потребление можно померить только объемом. Весь фокус в том, что выделение памяти под данные тоже не бесплатное и, в зависимости от ситуации, может быть выгодно забить больше памяти, но сэкономить на аллоках в конкретный момент. С оценкой по процессорному времени хуже — грубо говоря, чем более целевая платформа не похожа на x86 (условно — на CISC/гибридный процессор), тем больше шансов получить адекватно работающий алгоритм на ПК и неприемлимо медленно работающий, например, на ARM (самый простой пример — алгоритмы, использующие много деления на ARMv7-A, где деление не является процессорной инструкцией).

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

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

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

И включая в себя тот известный факт, что четкие и детализированные требования — главный враг любимого аттракциона «а можно ещё вот что сделать».

Использую mind maps для быстрого структурирования задач по проекту, для последующего сотрудничества с клиентом. Занимает 2-3 часа и дает целостность картины на одной странице. Может подойти не для всех случаев, но для консалтинга пока достаточно. Софт Mind Manager 2012, крутая вещь, но платная.

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

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

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

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

4. Ну и, наконец, про

Когда люди строили первые хижины, они не начинали с плана, то же с автомобилями, самолетами и т.п. Или они отказались бы, посчитав, сколько все это стоит ?

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

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

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

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

пункт про моральный прессинг зачастую возникает именно из-за андерэстимейтов.

Скорее, наоборот — андерэстимейты нередко возникают из-за прессинга сейлзов/менеджмента. Хотя, не спорю, бывают и чисто технические просчеты, особенно когда эстимейт доводится делать необстрелянным новобранцам.

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

Э... Ну как бы смотря, что делать. Фейсбук планировать смысла, наверное, нет — его писать неделю (: А какой-нибудь фреймворк или CMS не грех и попланировать. Честно говоря, просто не представляю себе некоторые работы в кавалерийском аджайл-наскоке. Ну например, документооборот, сложный билинг, распределённый магазин, медицина, 3Д.

Ну да, чай к (наболевшему) Diablo III никакой аджайл не применишь)

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

Если двигатель не перебирать конечно

Судя по тому, что у них игры по 10 лет делаются, там, наверное, двигатель не то, что перебирается, а редизайнится раз 5.

Фейсбук планировать смысла, наверное, нет — его писать неделю (: А какой-нибудь фреймворк или CMS не грех и попланировать.

По-моему, это прекрасно!

Извольте объясниться, сударь.

Не нахожу в себе сил, сраженный глубиной анализа.

Будите искать, посмотрите там же чувство юмора.

Ах, вот оно что, шутка юмора. Понимаю. Петросяну привет передавайте.

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

Присылайте 100500 тысяч денег, я начну макет рисовать.

Ну денежные вопросы можем обсудить и за чашкой чая Ж-) Думаю что за фейсбук можно разориться и на большее... В общем — будет желание — мои контакты есть на сайте.

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

Я ж не сказал «научу» Ж-) я сказал — покажу — а вы разве никогда не видели рывок штанги ? :-)

Планирование с продумыванием архитектуры не путаешь?

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

Мастер Йода при виде этого комментария поперхнулся чаем.

Не «калил» я ни с форумов ни с доводов! Сам дошел. Все буквы в песне мой личный опыт. Сорри, конечно, за велосипед.... Что то весной наверное навеяло :-)

Спасибо, что думаете сами и не стесняетесь делится этим, серьёзно, тут статей таких не много.

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

Хорошее планирование предполагает, что цель проекта более-менее неподвижна, и, соответственно, можно заранее составить план по ее достижению — пусть даже с допусками на риски.

В реальности же бывает так: заказчик настаивает на fixed-all контракте, командой тратится время на детальные спецификации и планы, а потом заказчик начинает менять половину требований по ходу проекта.

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

Все участники проекта должны понимать что план — это как архитектурный проект здания. А вот любые сроки — это «предсказания». Когда реально достроят дом — это не от проекта зависит а от 100500 разных факторов.

Маленький нюанс. Когда строят дом — заказчика вдруг не клинит и он не начинает требовать сместить окна на 20 см влево.

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

Альтернативное название статьи:

«Объяснение преимуществ agile перед waterfall, без употребления слов „agile“ и „waterfall“.»

Ой не надо, agile имеет те же проблемы при планировании дальше одного спринта.

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

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

Так к этому нужно не разработчиков призывать, а заказчиков, которые требуют подобные детальные планы (вплоть до ежедневных планов загрузки каждого разработчика на месяцы вперед), настаивают на fixed-all контрактах и т.п.

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

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

Полностью согласен — иногда это просто бюрократия. Тему доверия попробую раскрыть в следующей статье Ж-)

Когда условия тендера требуют определить план майлстоунов и дату конечной поставки, или когда мы, как компания-подрядчик, пытаемся уйти от time&material-модели в fixed price, чтобы поднять больше денег — это даже не бюрократия, а реальные требования рынка.
Имхо, важность управления рисками слегка преуменьшена, про assumptions ничего не сказано, и доверие почему-то ставится в противовес фиксированной оплате — из моего опыта они часто (хотя и не всегда) идут рука об руку.
В целом большое спасибо за хорошую статью!

Подписаться на комментарии