Как стать автором
Обновить

Комментарии 47

Спасибо. Было бы интересно почитать такой анализ для большого проекта, где пятисотстраничный талмуд-ТЗ дают вместо первого требования, а апдейты к нему (шестисотстраничные) вместо остальных. (Ответ типа «ничего не меняется» тоже сгодится. :))
Где-то то же самое. Так, как в посте, возможно начать проект. Далее он где-то так и развивается. Я не люблю UML, как и многие, кто следует такому YAGNI. Но общие черты, алгоритмы, документируются. После кодирования. Для проектирования не особо нужно.
А для передачи знаний — сгодится. Но лучше всего должны документироваться требования. Т.е. как-то собираться, структурироваться. И они связаны с автоматическими тестами.

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

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

Я часто общался и спорил с коллегами по поводу целесообразности YAGNI. Но это никак нельзя объяснить просто на пальцах. Это навыки оценки и рефакторинга кода. А говорить о теории можно сколько угодно. У оппонентов возникают сомнения не в том, что это, а в том — как это вообще возможно.

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

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

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

Вообще спасибо автору за хорошую статью. Однако в истории про Бориса и Маркуса речь шла не о YAGNI, а о KISS — там шла речь о том, что система должна быть простой. Борис ничего лишнего, не относящегося к требованиям, не реализовывал.
Вот в этой книжке приведен замечательный пример реализации данных принципов на реалистичном примере (реализация программы по работе с боулингом).
Спасибо за книгу.
Ошибся, ответ ниже
Любые классы вообще поменять проще пареной репы, пока их никто не использует.
Во избежании неверного толкования (которое имело место), поясняю, что имею ввиду, что созданные в рамках статьи классы не используют другие слои приложения и именно поэтому их вроде бы легко рефакторить.
Например их наверняка будет использовать UI системы.
Согласен, вот так легко — бац и все поменялось. А в реальной жизни, часто нужно делать так, что бы и старое. и новое работало.
Книжка отличная. Кстати, есть в продаже более позднее издание 2011 года и в электронном виде: Тыц. P.S. В бумажном виде не осилил: тяжелая, мягкий переплет, все время захлопывается.
Спасибо за книгу.

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


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

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

KISS и YAGNI по-моему, почти одно и то же. Простота и отсутствие функционала, без которого можно обойтись — близкие понятия. Если говорить о простоте, то очень относительное понятие. Борис делал много лишнего (или вы ошиблись, хотели сказать Маркус?). Откуда он взял микроволновки, откуда повара? То, что ему казалось логично — просто его представления о мире, которые он реализовывал, пытаясь угадать, как пойдет разработка дальше. Т.е. постелить солому туда, где может упасть. И очень быстро забросал соломой весь ландшафт и ходить не смог ))

В комментариях там много говорилось о некой золотой середине. Т.к. предполагалось, что Маркус не делал рефакторинга и не думал вообще, чем его ветвления обернуться потом. Т.е. неверное понимание YAGNI.
Как-то там стал вопрос — планировать (Борис) или нет (Маркус). И думали многие о середине. Тут нужна не середина. Однозначно — не планировать. Но и не запускать код, пока с него будет невозможно выбраться.
Еще раз спасибо за интересную статью.

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

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

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

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

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

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

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

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

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


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

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

В гибких технологиях разработки много внимания уделяется обмену знаниями, ревью кода и чтобы программисты менялись местами (никто не владел куском кода единолично).
Вы говорите о практике экстремального программирования Collective Code Ownership,
К Agile этот принцип имеет лишь очень косвенное отношение.
А практика Code Review — вообще к Agile никаким боком.

Говорить об agile стало так модно — статьи не пишет только ленивый. При всем уважении — настоятельно рекомендую ознакомится с мат частью. И начать рекомендую с Agile Manifesto.
Да, ладно. Как это не имеет? )

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

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

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

Менеджерские и девелоперские методики, которые удовлетворяют данным ценностям и правилам — мы называем Agile методиками. Да — экстремальное программирование в принципе Agile методика, но конкретно практика коллективного владения кодом не является прямым следствием правил Agile-а, а лишь косвенно с ними связана.

Коллективное владение и инспекция кода — никакие не пожелания а конкретные практики, которые применяются определенным образом.

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

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

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

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

Ревью кода, в моем понимании, — это далеко не одобрение. На одобрение можно ложить с прибором. Считаем, что коллектив взрослый и папа никому не нужен. Если начнется одобрение/неодобрение, то начнутся нехорошие вещи:
1. Если разработчик, ведущий ревью, по рангу не выше, то неодобряя код может напороться на серьезное сопротивление.
2. Если нужно одобрение и не выполняется пункт 1, то тогда появляется некий папа, который ревьювит код и разрешает комитить.
Во втором случае не происходит обмена знаниями о коде, о частях системы. Поэтому ревью проводится не для одобрений на основе которых делаются выводы о комите. Ревью кода — это другие разработчики проводят, желательно, не близко связанные с этим участком. Тогда они вдумчиво читая, находят до 90 процентов багов. Даже юнит-тесты меньший процент дают. Далее, они действительно сохраняют комментарии в документе по поводу читаемых и нечитаемых мест. Что очень полезно разработчику, который писал код. Он может не обратить внимания на ревью или доказывать, что считает, что его код правильно написан. Но тем не менее, информация для него полезная и может принять к сведению.

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

Вы правы — я немного переборщил с определениями в угоду лучшего понимания моей мысли.

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

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

Практику код — ревью следует применять для улучшения качества кода. И совершенно наплевать есть ли парное программирование или нет. Главное достаточно ли хороший получается код.
И уж конечно код ревью не имеет никакого отношения к agile.
Как мне кажется, это переупрощение. Позволю себе сочинить список требований.
1) Игра походовая. Сетка гексагональная. Солдаты ходят, друг друга рубят, либо стреляют.
2) Герой должен иметь свои характеристики, которые добавляются к солдатам, плюс сам должен уметь периодически швырять какое то заклинание. Сила регулируется какой-то характеристикой героя, плюс само заклинание может быть одного из трех уровней.
3) Добавить магов, Маги должны швырять ту же магию, что и герой по типу, но рассчет силы от количества солдат. Отличие от стрелков — магия накладывает пост-эффекты, например горение постепенно сжигает здоровье, а оглушение не дает ходить какое то время и т.п.
4) Добавить препятствия и летающих солдат. Ну и сразу непролетаемые препятствия и телепортирующихся солдат.
5) Добавить солдатам активные расходуемые навыки, например лучник может один раз за игру огненную стрелу запустить. Также пост-эффекты.
6) Добавить персональные свойства, например тяжелобронированные солдаты получают меньше урона в ближнем бою, а «ловкие» периодически уворачиваются от урона, но не от магии.

На этот момент аццкая лапша имхо обеспечена, если изначально подходить к делу энумерацией. А фантазий у геймдизайнера еще немало.
Нет, тут как раз энумерацией описываются только тип магов (или его специализация). Все объекты логики приложения остаются объектами (с отдельными классами) и в коде тоже. То есть солдат и маг — абсолютно разные объекты с разными характеристиками, пусть и унаследованные от общего класса юнит. Вообще в приложении любой объект со своей логикой должен быть отражён не больше и не меньше так же, как и в человеческом описании. То есть у вас есть Герой с Юнитами (маги, воины, стрелки, разведчики), Карта с Препятствиями (брёвна, озёра, горы и т.п.) вот как вы их описали бы дизайнеру или другому разработчику, так и должно оно выглядеть в коде. Чтобы я мог заглянуть и сразу найти класс Маг и посмотреть что и как я могу поправить в его интерфейсе/реализации, безо всяких лишних бредовых лишних сущностей.
Исходя из первого требования, солдат — не более, чем свойство клетки. Возможно, битовое. В какой момент и почему он станет объектом (и станет ли) — это еще вопрос. Возможно, только после того, как свободных битов не останется — но и тогда дешевле будет клетку сделать 64-битной.
Отличные требования )
Правда писать весь код, чтобы показать как, это будет стоить дороговато. Хотя без графики за несколько дней можно написать, показывая, как инкрементально добавляются требования. Вот, если бы какое-то 7 требование противоречило более раннему, проблем было бы больше. Например, что сетки больше нет, а солдаты не рубят друг друга, а играют в карты ))) Проблемы с таким требованием были бы при любом подходе к программированию. Но эволюционное — снижает затраты.

1) Игра походовая. Значит, есть одно состояние в один момент. Как минимум. И возможность перехода в новое состояние. Есть солдаты и есть у них координаты. Плюс поведение — рубят и стреляют. Понятно.
2) Появляется Герой. По всей видимости, игра двух или несколько игроков, живых или компьютера. Игрок владеет героем, герой войском. Игрока мы не моделируем. К каждому солдату добавляется ссылка на Героя. Свойства становятся динамически вычисляемыми, в зависимости от свойств Героя.
3) Маги. Насколько я понял, это новый тип солдат. Ага, у нас бывают разные типы. Первые только рубились и стреляли. Маги только стреляют. Магией, а не пулями. Тогда мы расширяем солдат, делаем базовый и наследники. Маг, таким образом, также как и солдат, связаны с героем. Поэтому сделать расчет силы удара мага в зависимости от количества солдат, которыми владеет Герой — не представляет проблем. Такие умения даются почти даром в смысле кода. А, да, забыл. Это не обычная стрельба, т.к. ведет себя по другому. Ну и отлично, список действий фигур (будем так называть солдат и магов) расширяется до трех: удар, стрельба, швыряние магии. Горение от магии «постепенно» сжигает здоровье. Значит в фигуру добавляем еще список «заклятий» и счетчик связанных с ними ходов. Запрет ходить можно сделать пока отдельно, по сравнению с другими действиями, вроде горения. Не обобщаем.
4) Добавить препятствия? Легко. До этого мы структуру данных, моделирующую сетку, не делали. Была не нужна. Теперь сделаем. Тем более, что при появлении препятствий появляется более сложный алгоритм движения — поиск кратчайшего пути для бота, например. Хотя, о ботах не говорили. А и для человека нужно, если он будет указывать конечную точку движения солдата. Летающие солдаты и ходящие имеют разные алгоритмы передвижения. Реализуется какой-то «стратегией» (паттерном).
5) У солдат уже есть возможность гореть некоторое количество ходов, значит есть способ расходовать что-то по ходам. Если не надо по ходам, а это, допустим, количество стрел, так тогда делаем класс Оружие, который имеет конечный или бесконечный ресурс. Обычное оружие — бесконечный, лук — конечный (при каждом использовании счетчик уменьшается, пока не достигнет нуля). Пост-эффекты уже есть, маги постарались.
6) Тоже никаких проблем. Делаем свойства по умолчанию, потом, при создании экземпляра солдата, некоторые характеристики меняем. Но если нам нужно еще отображение этих свойств (доспехи или что-то подчеркивающее легкость и т.д.), добавляет список артефактов солдата, а его свойства суммируют его личные навыки и полученные от артефактов.

Мне тяжело представить, как это сделали бы без эволюционного проектирования. Вот, я писал эту статью. Концентрировался на коде. Казалось бы, очень простой код и каждый раз я с помощью элементарных соображений приходил к выводу, что и как менять. Но если конечную схему классов нарисовать, то она уже довольно большая. Если бы я сразу пытался всё охватить, все ваши требования по игре и нарисовать схему, то сложностей было бы больше. Я пытался бы всё охватить. А это тяжело и не нужно.
Ну вот, сразу появились «стратегии», базовые и наследуемые классы и пр. Я имел в виду то, что «хлеб» в исходной статье это переупрощение. Вряд ли кто-то пожелает, чтоб ему закодили сделать пустой класс, без состояния и поведения, в котором только тип BakeryProduct type. В реальном мире у него будут методы и события, в каждом торте и пирожке свое, и тут получится либо четырехкратный if-else, либо большой нечитаемый switch. Если его не делать изначально базовым с наследниками, то рано или поздно он придет к состоянию, когда все придется переписать с нуля, даже если требования заказчика не метания белки по лесу, а логичные и последовательные. Принцип YAGNI он, конечно же, более чем правилен, создание лишних сущностей и лишних связей между ними Борису явно не стоило даже пытаться делать. Но и Маркуса это никак не оправдывает, и то что, благодаря переупрощению, код получился без лапши еще не означает, что в реальном проекте ее не будет.
С одной стороны не надо пытаться предусмотреть какие то «изменяющиеся сущности», которых нет в требованиях, а с другой стороны не надо писать «универсальный код», когда эти сущности уже есть, лучше его разнести по классам, а не по if-else. Тут где-то и кроется та самая золотая середина, как мне кажется…
Пустой класс хлеб — вполне нормально. Если у него нет поведения пока по требованиям.

Я иногда и пустые интерфейсы пишу. Зачем? Чтобы знать, что класс его поддерживает.
Это конечно, редко и скорее всего не нужно. Но это на «вырост». Добавляются потом какие-то методы и т.д.

Так и с хлебом. Надо начинать развивать проект с чего-то? Есть хлеб, как класс, как сущность, которая отличается от других, но ПОКА не имеет ни состояния, ни поведения. А угадывать наперед я не хочу. И пока концентрируюсь на том, как закодить работу с этим объектом, а не что он делает. Это позволяет по частям развивать архитектуру.

switch и if-else не так плохи сами по себе. Тут тоже расчитывать надо баланс. Если любые ветвления заменять виртуальными методами, то ничего хорошего не получится. Код будет не читаем. Будет много классов, да еще скорее всего в разных файлах. И чтобы понять, каким образом происходит выбор, придется долго в код смотреть, переключать страницы. При небольшом количестве елементов в switch — может быть гораздо лучшим решением. Смотрите на метод и пытаетесь понять, насколько легко читается. Если легче будут уже классы — переходите на классы. Как промежуточный вариант, можно структурами данных моделировать — Dictionary<>
Пустой, или как его еще называют, маркерный интерфейс это вполне нормальное явление, даже в готовом продукте. А вот пустой класс заранее понятно, что он должен будет что-то из себя представлять.
И кстати совсем необязательно делать общехлебный интерфейс, ведь он же понадобится только при потреблении хлеба, а не при производстве, те есть может он нам и не будет нужен совсем. Чуть более простым кажется вариант, где у печей по методу на хлеб, пирожок и торт. Ну и на кирпичи понятное дело.
Но, даже заранее не зная что будет дальше, делать их все одним классом с перечисляемым полем… ну даже не знаю, у всех свой путь самурая, конечно же.

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

Писать пустой класс, я тоже часто пишу. Допустим, я знаю, что буду работать с неким объектом. Но мне надо написать некие алгоритмы работы с ним (позже они могут перенестись в него самого, а он стать базовым и т.д.).

Но пока, создал пустой класс и ни о чем не думаю, просто оперирую им. Я не думаю в этот момент, как его будут использовать. Потом, в другой задаче об этом буду думать. Таким образом я всегда смотрю на код как-то локально.

Конечно, тут очень надуманная задача. Если нет ГУИ и совершенно не объясняется, что с объектом делает конечный пользователь, то и делать ничего не надо. Обычно требования пляшут оттуда. Но мне хотелось показать принцип, как размышлять. А не вообще все нюансы.

Объект, в котором внутри перечисление всего лишь — это способ такой упрощенной упаковки типов и не создавания наследников. Как только они станут нужны, тогда и появятся. При этом не факт, что перечисление исчезнет. Оно часто используется и далее.
Временный пустой класс, пустой метод и вообще любые заглушки не вызывают вопросов. Вызывает вопрос, почему класс один? Требование заказчика иметь три разных, хлеб, пирожок и торт. Зачем заниматься самодеятельностью и объединять их в один, награждая перечисляемым типом? Заранее же неизвестно будет ли у них что то общее вообще, состояние или поведение. А кирпич при этом отдельно, хотя про него нам известно ровно столько же, сколько и про торт, который впоследствии может оказаться сленговым названием газобетона например, и его имеет смысл с кирпичем объединять, а не с хлебом.
Совершенствоваться в применении YAGNI еще есть куда, не правда ли, хех.

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

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

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

Но когда еще нет поведения, то остается просто маркер типа.

Пример очень утрирован. Я его взял с предыдущей статьи другого человека. Понятное дело, многое пришлось за уши притягивать. Ваши требования для игры, возможно интереснее. Но статья получилась по ним бы гораздо объемнее.
Раз уж речь зашла о гейм-архитектуре, оставлю здесь эту диаграмму классов, датированную 2008 годом.
Много воды с тех пор утекло и нет особого смысла ее обсуждать, но не трудно догадаться какой ад последовал далее.
И пользуясь случаем еще раз передаю привет астронавтам архитектуры!
«Лично я знаю, что хлеб состоит из теста (муки, пшеницы или ржи…), что его можно купить в магазине и что его можно есть. Но это мои личные знания. Заказчик пока ни слова не сказал о каком-либо поведении или состоянии. А т.к. я человек ленивый, то хоть я и знаю немного больше, я и кнопку лишний раз не надавлю, без прямого указания на желаемое заказчиком.»

Все-таки в изначальной статье хлеб и печки были выбраны именно для того, чтобы не расписывать, что хлеб можно испечь (или купитьв магазине) и съесть, а кирпич съесть нельзя (не хотелось бы вместо хлеба все-таки). Ну т.е. подход YAGNI — ок, понятно, но здесь пример изначально гипертрофирован, что несколько портит эффект от дальнейшего чтения.
В этом и суть этой статьи!
Если вам заказчик говорит «хлеб», это ничего общего со знакомым хлебом не имеет.
Забудьте, что его можно печь или есть, пока такое требование явно не появится.

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

Ситуация #1:
Заказчик приходит и приносит ТЗ, в котором четко расписано, что такое хлеб, чего от него требуется в рамках разрабатываемого софта, описан техпроцесс изготовления и т.п. Ну т.е. достаточно четко, чтобы понять, что именно требуется заказчику, особенно если добавить сюда вводный бриф с заказчиком.
Тогда да, вспоминать, что хлеб еще бывает из кукурузной муки, или еще какие-нибудь достоверные, но не интересующие заказчика факты про хлеб — зло. YAGNI тогда именно то, что требуется.

Ситуация #2:
У заказчика есть бизнес-потребность. ТЗ нет, понимания, что это и зачем его готовить тоже нет. Тратить деньги и время на разработку ТЗ не хочет ни в какую. Говорит только, что ему нужна система, которая печет хлеб. Ок, по YAGNI делаем ему хлеб. Заказчик в ответ: вы чего, ребята? Этот ваш хлеб есть нельзя, вы его из чего вообще сделали? Ок, дорабатываем наш хлеб. И так много-много раз, пока заказчик не получит того, что ему нужно, либо не бросит эту затею из-за ощущения того, что он работает с дибилами, которые не понимают базовых вещей про хлеб.

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

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

P.S. мне как-то пришлось побывать в ситуации в роли аудитора вот в какой ситуации: заказчик не был в состоянии полностью, достаточно и непротиворечиво сформулировать требования к большой системе, а разработчики использовали подход, похожий на YAGNI, делая только то, что описано в требованиях к конкретной текущей задаче. Хорошо не получилось. Получилось «как-то», не смотря на то, что клиент был очень адекватен в своей области, с удовольствием и подробно рассказывал про то, зачем нужно система и как планируется ее использовать, а разработчики были достаточно квалифицированы, но не хотели углубляться в задачу заказчика. Как написано, так и делаем. Не хватило для хорошего результата здесь, на мой взгляд, только одного — тимлида команды (менеджера, аналитика, нужное подчеркнуть в зависимости от распределения ролей в команде), который бы использовал здравый смысл для того, чтобы понять, стоит уточнить у заказчика напрашивающийся потенциальный кейс использования или нет. И учесть полученную информацию.
Ситуация #2 вообще к проектированию классов отношения не имеет.
Даже при отсутствии ТЗ разработчики хотя бы между собой договариваются, какой функционал будет реализован на итерации. Здесь можно пофантазировать и попытаться связать потребность заказчика со своим опытом.

Таким образом, #2 приводится к #1 пусть не с внешним ТЗ, а хотя бы в голове одного разработчика, а дальше — YAGNI.
Ситуация 2 вполне часто бывает и обоснована.
Но в статье я всего лишь один срез показывал — ничего не делать без подтверждения заказчика. И это верно. Другое дело — вы не пассивны в общении с заказчиком. Там даже небольшой пример есть «вступаем в полемику».

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

Есть вариант, что заказчик не в курсе обо всех тенденциях и нельзя от него получить какую-то конкретику по каким-то направлениям. Тогда можете реализовывать любое. Так же, как в статье — какой-то взвешенный алгоритм наименьших квадратов. Заказчик может быть вообще даже и близко не в теме. Но тем не менее, есть возможность реализовать что-то, а потом спрашивать уточнение. Это что-то вроде рабочей заглушки. Но надо помнить, что это заглушка. И потом уточнить, даже если заказчика устраивает.
А вот под этим я подпишусь.
Не знаю, кто как, а я после слова pasty не могу думать о коде, если речь идёт о cornish pasty! :)
Это — прекрасная иллюстрация того, чем ценен опыт работы вообще, и опыт работы в конкретной индустрии в частности. Разработчик с опытом работы в хлепопекарной индустрии с самого начала скажет себе: «Эге, господин заказчик, без печки да рецептов для разной выпечки никуда вам не деться, все равно понадобится», и заложит их в код сразу — без излишних деталей, но так, чтобы можно было без масштабных потрясений и переделок потом сделать все, как надо. Да и заказчику напомнит — а не забыл ли он про эти важные мелочи?

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

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

Программист — это самурай проекта, а не самурай заказчика или денег или начальства. Программист болеет ТОЛЬКО за проект. И грош цена такому профессионалу, если он через это перешагивает. Вы, допустим, заказчик. Вы бы согласились нанять подлизу, который пытается вам угодить на словах, а пишет говнокод?

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

Ягни — это глубокая философия, как НАДО развиваться проекту. Это серьезная практика. Работа с кодом, умение оценивать, преобразовывать информацию.

При этом, конечно, должно быть и прямое общение с заказчиком. Никто не мешает программисту предлагать некоторые пути развития проекта с т.з. требований. Только в общении рождаются требования. И программист тоже может придумывать требования. Но только ОБЯЗАТЕЛЬНО их обсуждать с заказчиком, а не делать и строить из себя фокусника. Делать он может только то, что утверждено в обсуждении с заказчиком.

Конечно, не со всеми заказчиками надо работать. И нарушать технологию по желанию заказчика тоже неправильно. Есть некие границы. Грубо говоря, в идеале заказчик говорит ЧТО СДЕЛАТЬ, а разработчик говорит КАК СДЕЛАТЬ. И, в идеале же, если заказчик начинает последовательно заползать на территорию разработчика, то работать с ним не надо (хотя, конечно, он вправе высказывать некие пожелания и давать некие советы).

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

И да, конечно, если заказчик категорически настаивает на том, что печка не побнадобится, то делать печку не нужно. Хотя, пожалуй, и из этого правила есть исключения.
Так да. Верно.

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

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

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

Другой пример — разработка игр. Без project manager'a скоординировать работу сотни очень разномастных людей просто нереально. В этом случае он является каналом для общения с заказчиком — иначе будет полный хаос, и, опять-таки, конструктивного общения не получится.
Фраза «не надо с таким заказчиком работать» показывает, извините, ваш глубокий непрофессионализм. Дальнейший уровень ответа подтверждает это наблюдение.
Что только люди не придумывают, когда нет нормального аналитика.

А разве это Маркус? Это больше похоже на Бориса здорового человека.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории