воскресенье, 19 декабря 2010 г.

Конфигурябельность

Повествование в художественном или разговорном стиле на компьютерную тематику дело не новое. Наверное, одним из первых и самых известных представителей этого жанра является Том ДеМарко со своей замечательной книгой "Deadline. Роман об управлении проектами". Вот и я решил опробовать этот стиль на себе и посмотреть, что из этого выйдет.

*****************

Первые дни работы на новом проекте - очередной стендап. Мы, видите-ли, работаем "по скраму". То, что никто не понимает, для чего это нужно и какие бенефиты мы от получаем от этого процесса - дело второе, но главное, что все (в том числе и заказчик) знают , что у нас есть "Процесс" и мы его рьяно соблюдаем. Ну ладно, скрам, так скрам, назовите вы процесс хоть RUP-ом, только тысячами отчетов не задалбывайте.

На очередном стендапе я стою себе в сторонке, никого не трогаю, народ в это время обсуждает куски какого-то проекта, и тут Славка (лид наш) вспоминает о моем существовании, поворачивается ко мне и говорит:
- Серега, ты же сейчас ни чем особым не занят?
- Да вроде бы нет, - осторожно отвечаю я. - Мне Мэт еще на той неделе обещал подогнать какое-нибудь разумное задание, но так и не подогнал, вот я сижу и дурью маюсь помаленьку.
- Отлично, - говорит Славка, - У меня как раз к тебе заданьице есть. Возьмешься?
- Ну, а чего ж не взяться-то, раз оно есть-то. Давай, конечно.
- Вот смотри, ты же в курсе, что мы переписываем этот Loader с плюсов на шарп? Так вот, заказчик аж кипятком исходится, так хочет, чтобы он был конфигурабельный. Ну, типа, мы в конфиге чего-то прописали, и оно уже как-то по-другому работает.
- Ну, ладно, - говорю. - Идея-то разумная, а что сильно часто им приходилось правки вносить? - спрашиваю.
- Да, х его з, - отвечает Славка, - Народ говорит, что запросов на изменения, дескать, вообще не было, ибо они в этот г#$@о-код даже лезть боялись. Так что я не в курсе, насколько это на самом деле пригодится, но точно знаю, что без конфигурябельности они никуда не хотят.
- Оки, дай мне денек, я поразбираюсь в коде старой системы и в том, что вы уже успели наваять для новой версии, да покумекаю, стоит ли прикручивать сюда эту конфигурабельность аль нет.

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

- Блин, - говорю я Славке и другим ребятам на следующее утро. - Все же, на кой хрен нам нужна эта конфигурябельность прямо с самого начала? Почему бы не добавить ее позднее, когда мы уже точно будем знать логику нашего приложения? Ведь в старой апликухе, букав-то дофига и мы вполне можем проморгать что-то ценное ненароком. Почему б не сделать ее по-простому, покрыть ее тестами, показать ее народу, а потом уже заменить реализацию нескольких классов с хардкода на чтение из конфига?
- Серег, ну как тебе сказать, - мрачно заявляет Слава, - я уже трижды пытался убедить наших заказчиков забить на эту фичу, ну или по крайней мере перенести ее во вторую итерацию, но они ни в какую.
- Да это же хрень полная, - продолжаю возмущаться я, - Чем их не устраивает конфигурация во второй итерации?
- Они считают, что нам придется пол системы переписать, если не сделать этого сразу, - отвечает Слава пожимая плечами.
- Ну, блин, если через одно место написать, то и всю ее целиком переписывать придется, - настаиваю я на своем.
- А чего ты вообще переживаешь по этому поводу, - вмешивается в разговор Саша, - Тебе разве не пофигу, ну заказчик хочет, так давай сделаем, да и забьем на это...
- Ага, у нас (да и не только у нас) все системы написаны через одно место именно потому, что разным хотельщикам не объясняют, к чему их хотения могут привести, - не унимаюсь я. - Вот и получаются системы, которые нужно переписывать после того, как авторы систем сваливают из конторы. Что мы и видим в нашем конкретном случае.
- В общем, так, - говорит Слава. – Ты, конечно, можешь попробовать еще раз убедить их в том, что они не правы, но я бы этого не делал. В целом конфигурябельность не кажется такой уж сложной задачей, чтобы столько сил и времени тратить на ее обсуждение.
- Ладно, но поскольку я в предыдущем обсуждении с заказчиком не участвовал, дай я один раз все же попробую.
- Ну, ок, дерзай. Только не затягивай сильно. Давай на сегодняшнем митинге с ними это и обсудим, - говорит Славка. - Тебе хватит времени, какой-нить докУмент сваять к этому времени?
- Да, вполне, - говорю я радостно, в тайне надеясь, что у меня таки выйдет сделать то, что у моих коллег до этого не вышло.

Ну, докУменты ваять, это ж как с горы катиться. На нескольких страницах я излагаю свои мысли по поводу того, чему учат всякие Бучи и другие Липперты. Дескать, на кой хрен делать что-то сложное изначально, если это можно всегда добавить, просто засунув эту хрень в качестве детали реализации и спрятав ее за каким-то интерфейсом. И вообще, разумно восстановить старую логику приложения, написать тесты, убедиться, что модуль работает так, как предполагается. Потом изменить реализацию модуля и скормить новый модуль старым тестам. Так мы будем знать, что ничего не изменилось и появится хоть какая-то уверенность в том, что система работает так, как того требует спецификация (пусть ее и нет в формальном виде). Тем более все эти этапы нужны все равно, не зависимо от того будем ли мы делать конфигурябельность или нет. Получается, что вопрос один: нужно ли нам будет показывать заказчику промежуточный вариант системы, в которой логика будет зашита в код или сразу переходить к реализации кофнигурации, этот результат не показывая.

Ладно, докУмент готов, ребятами одобрен. С нетерпением ждем вечернего митинга.
- Джон, Скотт, добрый день. У нас тут появились дополнительные мысли по поводу нашей конфигурябельности, вы читали присланный Сергеем документ? - Славка берет быка за рога с самого начала разговора. - Что вы думаете по этому поводу?
- Ну что я могу сказать, - отвечает Скотт, "стейкхолдер" этого проекта со стороны заказчика. - Мысли вроде бы неплохие, и ссылки авторитетные, но, увы, доводы не убедительные...
- Как не убедительные, - вмешиваюсь я и пытаюсь рассказать обо всем об этом еще раз...

- Блин, да им просто делать не хрен! - возмущаюсь я после митинга. - Какая там, нафиг, простота! Да там выражения парсить нужно, а не иксемелину простую использовать. - Открывая старые исходники и тыкая пальцем в страницы кода, возмущаюсь я уже после митинга. - Нет там прямой зависимости между входом и выходом, там кода два ведра в исходной системе, а они хотят это все в конфиги впихнуть!
- Блин, да это же круто, - подключился к разговору Колян. - Щас найдем какой-нить парсер выражений, прикрутим его и все дела!
- Да, а еще можно CodeDom-ом заюзать, - предложил Славка, то ли в шутку, то ли серьезно.
- Ага, - поддержал я ребят, - А еще есть какие-то более изощренные способы самоубийства, кроме отпиливания себе конечностей ржавой пилой? Это ж из пушки по воробьям! Прикрутить всякую хрень ради проверки двух десятков условий, которые кто-то хочет вынести в конфиг! Причем никто даже не знает, как часто эти условия будут меняться или добавляться.
- Вы себе представляете процесс дебага, когда юзер вам скажет о том, что ваша дудесная система работает не так, как он того предполагает? - не унимаюсь я. - В гонфиг бряку-то не поставишь...
- Ну, а что нам остается? - пытается утихомирить меня Слава. – Кроме как привести несколько вариантов реализации, каждый со своими плюсами и минусами, и предложить им самим сделать выбор.
- Ладно, - говорю я. - Так и быть. Попробую воспользоваться доктриной морпехов, которые должны следовать приказам командования, как своим собственным, даже если они с ним не согласны. Все, я пошел искать нормальные решения с этой, блин, конфигурябельностью...

------------------------------------------------
- Ну и чем же закончилась эта история? - спрашивает Саня с нетерпением. - Таки ты был прав или нет? Был ли вообще смысл от этой конфигурябельности? Ею вообще, хоть кто-то пользовался? - возбужденно тараторил Саня.
- Погоди, Санек, не так быстро, - отвечаю я с улыбкой. - Я таки подготовил несколько вариантов конфигурации, три варианта десериализации деревьев выражений .net-а (a.k.a. expression trees) из текстового представления ну и еще один - в виде чтения таблицы истинности из конфига. Вариант без конфигурации они отбросили сразу, так прикинь, я еще больше часа потратил, убеждая их, что в нашем случае полная таблица истинности будет занимать десяток страниц и будет совершенно нечитаемой. И только из-за того, что именно вариант с таблицей был предложен одним из заказчиков.
- Так на чем таки остановились? - перебивает Саня.
- Нам таки удалось убедить, что парсинг выражений с помощью Dynamic LINQ-а - это нормальный вариант, который как раз и будет тем компромиссом между читаемостью, расширяемостью и тестируемостью. Причем самое забавное то, что на реализацию всей этой конфигурябельности ушло значительно меньше времени, чем на обсуждение ее необходимости. Но мне кажется, что мы время потратили не зря. Попытайся мы реализовать эту задачу в лоб, в том виде, как хотел заказчик изначально, мы получили бы проблемы в реализации, не говоря уже за тестирование или сопровождение в будущем.
Даже в этой версии мы уже столкнулись со сложностями отладки и диагностики, но благодаря тому, что я сохраняю не только откомпилированные функции, но и сами выражения, вылавливание “блох” является задачей решаемой.

Я не знаю, пригодится ли конфигурябельность на практике и насколько она усложнит понимание этой части системы в будущем. Но мне было интересно работать над этой задачей, я разобрался немного с Dynamic LINQ-ом, попинался с заказчиком, и нашел весьма неплохое решение поставленной задачи. Мы сделали главное, мы не вырубили ни одно из наших решений в камне и любая вещь, которая потенциально может измениться, спрятана внутри за абстрактным интерфейсом. Так что шансы на то, что какое-либо решение сможет оказать существенное влияние на жизнь этого проекта – малы. Я думаю, что с ним все будет в порядке, и его не придется переписывать снова, когда у кого-то возникнет необходимость поправить в нем несколько строк кода. В общем, все будет с ним ОК, куда он денется теперь, с подводной лодки-то:)

11 комментариев:

  1. Нет, что и говорить, интересная история :) забавная даже..

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

    И еще один маленький коментарий, на случай если Вы, Сережа, захотите развивать себя в этом жанре повествования: нельзя строить историю на принципе "Все вокруг п.....сы, один я Д'Артаньян", уж лучше в таком случае выбирать героем повести не себя, а другого персонажа, а себя выставлять как случайно проходившего мимо человека имевшего такое же мнение как и главный герой;)

    Все вышенаписаное есть мое суровое ИМХО, ни цели обидеть, ни поучить чему то этим постом я не преследовал, автор имеет полное право на собственное виденье и изложение вещей :)

    ОтветитьУдалить
  2. @Максим: ИМХО Ваше просто отличное! Спасибо за мнение и я правда подумаю в следующий раз о публикации от третьего лица, а не от первого!

    З.Ы. Можно на ты? А то как-то не привычно в компьютерном сообществе на Вы общаться:)

    ОтветитьУдалить
  3. Интересная статья. Спасибо.
    По поводу Конфигурябельности. Столкнулся недавно с этой проблемой с другой стороны. Новый продукт, и вместо того, чтобы посидеть обдумать/обсудить требования, нам выкатывают какую-то абстракцию и говорят, вы сделайте конфигурябельно, а мы потом сами настроим как нам надо/понадобиться. И вот тут совершенная жесть начинается. И та же проблема, не хотим слышать ничего другого, дайте xml конфиг. Так и задумываешься о каком-нибудь скриптовом языке внутри приложения....

    ОтветитьУдалить
  4. @Pavel: Вообще очень многие люди склонны считать, что даже с кандачка им будет виднее, как что-то должно быть сделано. Вот и получается, что люди выдвигают очень часто требования, слепое следование которым приводит к сложным и слабопонятным решениям: заказчик не понимая всех деталей дает задание, а разработчики его полностью не понимая что-то слепо реализуют. Потом, как это часто бывает, это "что-то" идет благополучно в топку.

    ОтветитьУдалить
  5. Да уж. Все как у всех. У нас в команде тоже много пишут фабрик, абстрактных фабрик, кучу реализаций шаблонов. Когда спрашиваешь - ЗАЧЕМ? Ответ, чтобы было ГИБКО. Я уже даже поспорил с одним товарищем, что код, написанный как НЕМЕРЯННО расширяемый в будущем - через полгода останется ТЕМ ЖЕ. Никто не спорит делать надо хорошо, т.е. те же паттерны - отличная вещь, но зачастую используется как из пушки по воробьям. Для себя сделал вывод - искусство программирования - это умение находить ПРАВИЛЬНОЕ решение. Которое, в одном случае будет супергибким, а в другом - простым и кондовым. И вот понять где и как надо делать - это МАСТЕРСТВО.
    P.S. Если кто знает методу, как можно ЧЕТКО определить, необходимо ли делать СУПЕРГИБКО, киньте ссылку.

    ОтветитьУдалить
  6. Когда я занимаюсь анализом, архитектурой или проектированием какой-то возможности я помню о нескольких правилах:

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

    2) не стоит создавать обобщенное решение заранее. Почитайте Липперта, послушайте Боба Мартина; создать обобщенное решение изначально *практически* невозможно. Конечно возможно, что вы слеплены из другого теста, чем другие тысячи разработчиков, но я ставлю на то, что ваше обобщенное решение никому не пригодится и затраты на его реализацию не окупятся.

    3) создавай простое решение с точки зрения здравого смысла и общеизвестных практик проектирования (эти практики появились до того, как все стали говорить о пользе ООП, паттернов вообще и всяких S.O.L.I.D. в частности). Простое слабосвязное решение всегда достаточно легко расширить и добавить дополнительную гибкость. А вот обобщенное решение не всегда легко можно расширить, если вдруг вы столкнетесь с ситуацией, когда вам нужно что-то, выходящее за вашу же общность.

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

    В общем, простота - это сложное дело:)

    ОтветитьУдалить
  7. Здорово, спасибо за коммент. Uncle Bob уже как дядя родной :). Да и Липперт - не чужой уже :). Буду еще больше расширять кругозор. Просто устал уже. На слова - но это же будет гибко и отвечает SOLID принципам - зверею уже(против SOLID - ничего не имею, даже за :)). Показателен пример. У нас товарищ изменял инсталлятор. В одном месте надо было выполнить ряд действий - он это сделал в функции - 20 строк. Все работает и казалось бы - забыть. Нет, товарищ сказал, что это не отвечает принципам и надо переделать. После этого - человек затратил еще 2 человеко дня, реализовано было через 7(!) классов и предусматривало ВСЕ случаи жизни. Произошло это полгода назад. После этого НИКТО в код не заглядывал и ничего с ним не делал. Я к тому, что решение из 20 строк - ВСЕХ устроило бы. Вероятность того, что код будет модернизироваться - около 0. Основываюсь на том, что в подобной работе еще никогда не возвращались к таким местам.

    P.S. Порадовала реакция разработчика - и так работало и так работало, но когда я разработал диаграмму классов, реализовал ее - получил fun. 20 строк были написаны за 30 минут, а полная реализация и тестирование 7 классов - 2 человеко-дня.

    ОтветитьУдалить
  8. А сейчас, несколько лет спустя, Вы можете сказать, что это был за проект, или Ваши DNA ещё действуют?

    ОтветитьУдалить
    Ответы
    1. Ну, NDA особые уже не действуют, да и рассказывать особенно не о чем. Это был обычный ынтЫрпрайзный проект, который перекладывает данные из одного места в другое, выполняя определенные бизнес правила над финансовыми инструментами. Собственно, именно эти бизнес правила и было решено конфигурировать.

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

      Я не помню, чтобы этот кусок когда-то потом правили, но до сих пор считаю, что решение в лоб в этом случае было бы проще:)

      Удалить
  9. Возможно вопрос туп до невозможности, но что значит "сохранять откомпилированные функции и выражения"?

    ОтветитьУдалить
    Ответы
    1. Речь о том, что в программном коде есть два поля: Expression> _addExpression; и Func _addFunction = _addExpression.Compile();

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

      Удалить