13 Май 2009 г.

RSDN

Интересно, когда на RSDN перестанут задавать вот такие вопросы?

26 Март 2009 г.

Manager

В слове project manager man должно означать "мужчина; человек слова"

15 Март 2009 г.

Бузинесс-правила

Рассказывать долго, проще сказать так -- business rules Разбираюсь, перспективы мутноватые, хоть так, хоть так, хоть вот энтак. Так номер 1 -- listma, решение короткое и компактное, но.. одноразовое, что ли. Вариант с кастомным движком даже не рассматривается -- по простой причине "и так дофига писать" :).

То, что нашел для себя -- drools.net. Кто-нибудь пользовал? Каковы впечатлений?

Для тех, кому интересно -- http://www.ibm.com/developerworks/ru/library/j-drools/index.html?ca=drs-ru-0130 (на великом и могучем, т.е доступно).

8 Март 2009 г.

42 немоида

Вот здесь небезызвестный Андрей Плахов представил миру концепцию "томо-тоне" -- язык странных существ, "живущих в океане Европы" (с).

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

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

Рискну предположить следующее.

Учитывая, что недавно в Рунете произошла презентация нового сервиса "Яндекс.Ответы", можно предположить, что "движок" базы знаний имеет много общего с той системой, которая названа "томо-тоне". Также можно сделать вывод, что Яндекс в лице Андрея Плахова успешно решил задачу "томо", и сейчас находится в процессе решения "тоне".

Анализ сервиса "42" позволяет сказать, что как минимум пункт (в) выполнен, (а) и (б) в процессе улучшений.

Так это или нет -- мы еще узнаем.

3 Март 2009 г.

Arch o_O?

Philip Johnson: "Architecture is the art of how to waste space".

Отсюда 2 вывода:

  • Чем меньше архитектуры, тем лучше;
  • В 64хразрядную машину архитектуры влезет больше, чем в 32х :D

25 Февраль 2009 г.

Про код

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

20 Февраль 2009 г.

О методологиях

У нас внедрена модифицированная методология WATERSCRUM -- к процессу разработки все относятся как к госслужбе, а с первой итерации не выходит ни одна фича :)

18 Февраль 2009 г.

От Dll Hell - к Framework Hell


Кажется, совсем недавно Доктор Балмер обещал полное излечение от болезни, именуемой Dll Hell. Вкратце - это когда приложение зависит от сторонних библиотек, не обеспечивая бинарной совместимости между версиями. В эпоху COM это вообще превратилось в страшную эпидемию, потому что любой "залетевший дятел.. ну, вы поняли, что дальше" :)

Казалось, что .NET Framework будет той самой панацеей, но.. увы.

Болезнь мутировала (может, из-за того скальпель доктора был недостаточно прокипячен) и превратилась во Framework Hell. В попытках объять необъятное .NET Framework проскочил 1.0, 1.1, 2.0, 3.0, 3.5, 3.5 SP1 (3.6, я бы сказал), на горизонте 4.0 в продакшене и 5.0 в перспективе. И если вы хотите вздохнуть свободно, то -- не тут-то было :) Есть еще Compact Framework, Micro Framework (Microsoft'у не дает спокойно спать Kuawei VM), Silverlight (пока 2 версии) и XNA.

Не могу сказать, сколько это будет продолжаться. Можно пофантазировать, что очередная панацея -- это полное динамическое связывание (duck-typing) и отсутствие версий компонент как таковых. IronPython, IronRuby -- это первые ласточки. Erlang для .net -- будет и такое на нашем веку :)

12 Февраль 2009 г.

Про архитектуру cms (Хабр)


На "Хабре" (вот тут) опять предлагают и нахваливают полубредовые идеи сферических cms в вакуме.



Почему эта идея может быть плохой:
- от абстрактного "вот тут у нас будут модули, и они обалдеть как будут обмениваться информацией" до рабочей системы бесконечно далеко :( ;
- абстракция core/plugin придумана лет как 20 (Smalltalk, привет), все ее недостатки в литературе приведены, а в статье - нет, там - полная эйфория;
- "Модуль данных Data — самый важный модуль системы" (цитата) - это верно только если мы строим БД.
- При попытке остаться в рамках модели signal/slot, которая предложена, будут дырки в производительности, и ещё какие!; обход их выродится в "костыли", которые, к сожалению, быстро похоронят идею о тру message-oriented CMS =)

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

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

Как-то так.

9 Февраль 2009 г.

Scaling Out All Around Us, или Начнем масштабирование


Сегодняшний пост будет первой частью рассуждения вслух. О чем - увидите ;)

Часть первая. "Вы ничего не понимаете в //дизайне// масштабировании!"

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

(в порядке убывания приоритетов)
  • "читайте HiLoad и 'РИТ:Высокие нагрузки'" (кстати, зачем их разделили, кто-нибудь в курсе?)
  • "http://www.insight-it.ru"
  • "это конфиденциальная информация" (вариант: "это тянет на докторскую, а вы хотите, чтобы вам прямо так и рассказали, ага")
  • "берут и строят.."

Последний вариант отметаем сразу - рекурсивные определения нам мало чем смогут помочь, если мы не знаем, что мы хотим получить. Предпоследний - по-моему, отдает маразмом :) Думаю, что те, кто отвечают в таком ключе, ни разу не решали данный вопрос на практике. "Говорить - не мешки ворочать", так сказать.

Едем дальше. При всем уважении к Ивану Блинкову (insight-it.ru) и нисколько не умаляя его способности донести сложное простым языком и выдать на-гора тонны полезных ссылок, начинающий "масштабироваться" программист в лучшем случае сможет построить копию одного из примеров архитектуры, которые Иван так подробно описывает, но не сможет победить всех "демонов", которых оная копия вызовет на свет. Видимо, надо начинать по-другому, с простого, с отдельных частей.

Это очевидно, что остается один, наиболее достоверный способ разобраться в вопросе - смотреть доклады конференций: полезные доклады, не очень полезные доклады, остальные доклады.

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


Специфика вводных:
  • фактически 2х-звенная стуктура (БД + сервер приложений/он же веб-сервер). 3х звенка - ересь. N-tier - отсутствует как класс;
  • БД - MySQL в "дефолтовой" комплектации, относительно плоская схема данных;
  • для 80% систем большая нагрузка именно фронтенда системы.
  • есть еще пункты, например, внесессионность (statelessness) и данные, доступные только для чтения
Специфика решений:
  • Практически всегда для полного описания революционного решения достаточно 30-40 строк кода на php/python, реализующего тот или иной паттерн (GoF), иногда с продолжениями. Все. Враг повержен, апплодисменты из зала :)
  • Практически всегда "революция" пишется "с нуля". Доведение существующего решения до "hi-load certified" - не наш метод :) А надо бы. А хотелось бы иметь такой опыт и видеть, что он существует.
  • Практически всегда это решение невозможно "повторить". В наше время индустриальных технологий побеждает то, что может быть легко воспроизведено без потери качества. Этого нет;
  • Практически всегда решение не является архитектурным новшеством, а использует некоторое специфическое знание о компонентах, на которых основано.


Второй неприятный момент - создается ощущение, что те, кто используют что-то отличное от nginx + php/python + mysql, не имеют права на то, чтобы сказать "мы масштабировались". "У вас nginx? Нет? А о каком масштабировании вы тогда говорите". "У вас php? Нет? Вы ничего не понимаете в масштабировании!". "MySql? Эээ, а что вы тогда хотите?". И это ощущение влияет ничуть не меньше на выбор технологии, чем сравнительный анализ самих технологий (Поднимите руки, кто когда-нибудь его делал. Чья рука поднялась? Опустите немедленно, вы слишком выделяетесь).

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

И не менее часто ставится задача увеличить производительность (или запланировать увеличение) - на слишком большую величину, чтобы ее можно было зарулить просто оптимизацией и профилированием, но малую, чтобы ковыряться с полновесными кластерами и NLB. И - джентельмены - вы не поверите, но у меня Tomcat и сервлеты. Или веб-сервиc asp.net и ms sql. Не php. Не nginx, не FastCGI. Видимо, оттого, что я ничего не понимаю в масштабировании. Видимо, именно оттого появляются мифы, что по-настоящему быструю систему на asp.net создать невозможно.

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

На этом на сегодня все.

27 Январь 2009 г.

Перевод 25 причин за то, чтобы не начать писать свой OR/Mapper

Не мог не поделиться с сообществом этой публикацией — вольным перевод с английского статьи одного из соавторов (Oren Eini) известного фреймворка персистентности NHibernate "25 Reasons Not To Write Your Own Object Relation Mapper"; оригинальный текст статьи находится здесь (http://ayende.com/Blog/archive/2006/05/12/25ReasonsNotToWriteYourOwnObjectRelationalMapper.aspx).

По причине того, что Oren Eini aka Ayende пишет достаточно специфическим языком, ибо хорошо знаком с «изнанкой» OR-мапперов, перевод на русский был дополнен необходимыми пояснениями, которых нет в оригинальном тексте.

Итак, читаем

25 причин за то, чтобы не начать писать свой OR/Mapper, или Прочти всякий раз при разработке Data Access Layer

Не так давно меня попросили выбрать один из вариантов технологии построения слоя доступа к данным для кое-какого приложения. На выбор были предложены следующие варианты:

  • Закодить / сгенерировать по шаблонам DAL (Data Access Layer);

  • Использовать имеющийся OR-маппер;

  • Написать свой OR-маппер, специфичный для конкретного приложения.

Датасеты (DataSets) из ADO.Net оказались не очень подходящими для того приложения, поэтому первый и последний вариант — по сути одно и то же. Кроме того, схема БД — это не такая штука, которая только на основе ее позволит автомаГически сгенерировать код для доступа к данным, поэтому выбор свелся к тому, чтобы написать свой ORM или взять уже существующий.

Лично я рекомендую (а я присоединяюсь — прим. перевод.) NHibernate (ну, конечно! — прим. перевод.); тем не менее, первое, что приходит в голову - построить простую прослойку доступа к данным поверх хранимых процедур БД.

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

В общем, я сел за клавиатуру и составил список фич, которые мне понадобились от ORM в моем последнем проекте, использующем NHibernate внутри DAL. Некоторые из пунктов списка являются базовыми любого ORM, некоторые — просто очевидны, некоторые — просто особые приемы, которые я использую. Да, некоторые из них перекрываются и/или требуют наличия других пунктов, а некоторые — просто основа для других интересных трюков. Этот список основан на тех возможностях, что реализованы в NHibernate; и он в любом случае не полон. Конечно, я привык использовать некоторые другие фичи, о которых счас трудно вспомнить сразу. В мире полно ORM, которые не поддерживают весь список целиком; кроме того, есть несколько действительно крутых приемов, которые не реализованы и в NHibernate.

В списке так же подразумевается и паттерн Unit Of Work (далее UoW), который лежит в основе работы OR/M (таких, как NHibernate, DLinq и т.п.). Конечно, их работу можно организовать и по-другому (ActiveRecord, отсоединенные объекты), но я нахожу весьма привлекательным использование именно стиля UoW, который избавляет меня от необходимости ручного контроля изменений, примененных к объектам. Он так же очень близко отвечает той схеме, по которой обычно работают web-приложения (запрос на web-сервер — это, как правило, и есть UoW)

Короче говоря, вот они, эти пункты, безо всякого порядка :)

1. Транзакции.

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

2. Контроль конфликтов одновременного доступа (версионирование, исключение потерянного обновления, оптимистическая блокировка).

Обязательно должен быть реализован для выполнения любого рода операций с данными. Так же обязаны быть реализованными уведомления (обычно в виде бросания исключений) при попытке сохранить данные в ситуации, когда эти данные уже были отредактированы другим пользователем с момента их последнего чтения. Я предпочитаю реализацию, при которой версия объекта хранится в его специальном поле. Предпочтительно использовать тип TIMESTAMP при работе с MS Sql Server, и что-нибудь похожее при работе с другими базами данных.

Еще один способ отслеживать конфликты — проверять все поля колонки в таблице, чтобы узнать, не изменилось ли чего-нибудь с момента последнего чтения. Это способ несколько хуже, потому что он может вызывать проблемы точного определения изменений (например, тип DateTime может трансформироваться, когда путешествует между сервером и клиентом (прим. перевод.: web-службы до версии .net 2.0 некорректно обрабатывали локальное время)), также возникают проблемы с производительностью (прим. перевод.: из-за того, что приходится предварительно вычитывать данные перед каждой операцией записи). Еще один момент, на который следует обратить внимание при использовании такого подхода обработка NULL-значений; он также требует наличия информации об исходном состоянии объекта.

3. Встроенное кэширование (на каждый UoW и в целом на приложение).

Кеширование значительно увеличивает производительность приложения. Кеширование на каждый UoW означает, что если отдельный запрос требует некоторую порцию информации дважды в одном и том же UoW, ORM должен быть достаточно «умен» для того, чтобы вернуть информацию, сохраненную в памяти, вместо того, чтобы снова нагружать БД. Кэширование уровня приложения означает, что если одна и та же порция информации требуется в двух разных UoW, только запрос от первого UoW пройдет в БД, следующий будет обслужен из кэша. В идеальном случае это должно быть "прозрачно" для кода приложения. Такой кэш уровня приложения должен уметь корректно обрабатывать ситуации обновления/удаления/вставки записей, чтобы явно не пришлось писать обработку этих ситуаций в коде.

4. Поддержание идентичности (identity) объектов.

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

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

5. Политика очистки кэша.

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

6. Поддержка запросов.

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

7. Связи между данными.

В реальном мире данные в БД не ограничены одной строкой. Между различными таблицами обычно существуют связи. Эти связи тоже должны быть отражены на уровне объектов. Предпочтительно так же иметь поддержку обобщенных коллекций - как минимум наборов (Sets) и словарей (Maps).

Связи, которые нужно уметь моделировать (с примером в скобках):

  • "Один-ко-многим" ("Покупатель" — "Адрес");

  • "Многие-ко-многим" ("Пользователь" — "Роли");

  • «Многие-к-одному" ("Адрес" — "Покупатель") (прим. перев.: разница с первым - в том, где хранится и кто управляет связью).

  • "Многие-к-любому" и "Любой-к-многим" (вариация "многие-к-одному") — для поддержки коллекций объектов, реализующих интерфейс.

  • «Один-к-одному» ("Покупатель" — "Пользователь")

8. Группирование запросов.

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

9. Полиморфные запросы.

Запросы, применимые не только к одному классу, но и к его наследникам. Как пример: получить все правила, относящиеся к заданному объекту, если эти классы правил организованы в сложную ОО-иерархию.

10. Проверка на модификацию.

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

11. Возможность отмены изменений объекта.

Это - возможность установить объект в состояние, которое присутствует сейчас в БД (и отменить все изменения, которые были внесены в него, но не сохранены — прим. перев.)

12. Отложенная загрузка.

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

13. Ручное управление отложенной загрузкой.

Позволяет явно отменить поведение отложенной загрузки для коллекций, когда это необходимо. Решает проблему «N+1 запроса» (прим. перевод.: проблема состоит в том, что для объекта с «ленивой» коллекцией из N элементов отложенная загрузка «в лоб» вызовет выполнение N+1 запроса к БД - 1 запрос, чтобы загрузить объект и N отдельных запросов для каждого элемента коллекции, когда к нему обратятся - например, при итерации. В NHibernate, раз он принят как образец реализации, эта проблема решается либо явным указанием ранней загрузки всей коллекции вместе с объектом, либо группированием отложенных операций загрузки элементов коллекции, таким образом эффективно сокращая число «походов» на сервер БД).

14. Каскадные обновления.

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

15. Возможность отладки.

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

16. Безопасное использование в многопоточном режиме.

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

17. События жизненого цикла объектов.

Позволяет объектам приложения выполнять некоторые действия в ответ на события соответствующего типа, исходящие в ORM (обычно, как реакция на сохранение/обновление/удаление/загрузку записей в БД). Эта фича очень полезна для своевременного «подтягивания» некоторых данных из разных источников (таких как Active Directory, Web-службы и т.д.).

18. Стратегия обработки исключительных ситуаций.

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

19. Загрузка данных без загрузки объекта.

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

20. Составные первичные ключи.

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

21. CRUD-операции над сущностями.

Ну, тут и сказать особенно нечего.

22. Упорядочивание зависимостей.

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

23. Поддержка разбиения результатов запроса на страницы.

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

24. Поддержка произвольных типов данных, в том числе сложных.

ORM должен позволять выполнять маппиг как для простых, так и для сложных типов. Простейший пример - маппинг класса XmlDocument на колонку в БД типа XML.

25. Поддержка аггрегатных запросов.

Эта фича в OR/M позволяет исполнять запросы, содержащие такие вещи, как count(), sum(), avg() и т.д. Они нужны достаточно часто, и OR/M должен позволять использовать их.

Все 25 причин, которые я привел, должны натолкнуть вас на мысль, что написание своего высококлассного движка ORM - не такое дело, которое можно выполнить с легкостью. Он требует тщательного обдумывания каждого шага; и далеко не все пункты, которые я привел, решаются тривиально. Заставить их работать совместно оказывается очень непростой задачей. По моему мнению, это также не то, что можно перепоручить начинающему программисту.

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

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

P.S. Лично я еще и ненавижу дублирование существующего функционала только по причине синдрома NIH (Not Invented Here, «придумано не нами» или изобретение «велосипеда»).

31 Декабрь 2008 г.

С новым годом!

Ура! За 30 минут до конца этого года, всех читателей - постоянных и не очень - поздравляю с новым 2009 :) Пыщь-пыщь!

15 Декабрь 2008 г.

Process improvements - улучшения в процесс разработки

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

Выводы - примерьте документ к своей команде; возможно, он поможет найти то, что следует устранить.


PROCESS IMPROVEMENTS.
ИДЕИ И ПРЕДЛОЖЕНИЯ на тему «Качественно, быстро, командой»

ПОСТАНОВКА ВОПРОСА

Цель: пПредложить и обосновать коррективы в существующий процесс разработки для удовлетворения требований subj.

Задачи по оптимизации процесса разработки:
  • выполнить предварительный аудит и озвучить результаты (недостатки);
  • провести анализ собранной информации и конструктивную критику;
  • сформировать и выразить видение процесса командной разработки и предложить его оптимизацию.
Отправная точка:
  • некоторая действующая организация процесса разработки;
  • некоторое, достаточно большое, количество написанного в текущем процессе кода.
РЕЗУЛЬТАТ

Словарь документа:
  • «быстро» – означает, что решение задач любого масштаба в рамках процесса разработки укладывается в запланированные сроки и подразумевает пропорциональные затраты ресурсов. Для этого любая подзадача должна быть а) предсказуема по времени б) конечна;
  • «качественно» –­­­­­­­­­­­­­­­ означает наличие утвержденных критериев качества; задачи должны быть проверяемы на результат;
  • «командой» – означает, что каждый член команды разработки находится в mainstream проектных решений и согласен с ними;
  • SRS – software requirement specification; требования к проекту (грубо, ТЗ);
  • features – возможности программного обеспечения;
  • learning curve – срок полного вовлечения нового члена команды в текущий процесс разработки;
  • SCM – software configuration management - система управления конфигурациями ПО: в нашем случае – VSS/TFS;
  • customer expectations – ожидания заказчика; business rules – ожидания заказчика, оформленные в виде бизнес-правил будущей системы.
Негативные результаты, выявленные при аудите (внешние проявления и/или следствия):

Управление и общение:
  • недостаточно эффективная схема управления стратегическими и тактическими рисками проекта (рисками неудачи, рисками вероятных изменений);
  • отсутствуют схема и навыки управления сложностью конструируемого ПО;
  • недостаточная организованность в обсуждении и реализации требований.
  • недостаточно активное общение между разработчиками;
  • СОД (система обработки дефектов) не отвечает актуальному состоянию разработки;
Архитектура и код:
  • полное отсутствие SRS;
  • длинная и сложная learning curve;
  • отсутствие проектной документации; многие знания содержатся только в одном экземпляре - у ответственных девелоперов в голове (иногда – только у одного, который не такой уж и ответственный); некоторые из этих знаний критически важны для разработки проекта;
  • нестабильность поведения системы как результат серьезных дефектов архитектуры ПО (большое количество излишних неучтенных связей, противоречие ведущим архитектурным принципам (принципы SOLID), разработка по принципу «сначала сделаю функционала на 80%, потом костылями остальные 20% как-нть закрою и комментарии допишу» приводит к плачевным результатам);
  • низкая скорость добавления и удаления новых features, реорганизации кода;
  • плохое состояние кода (проявляется как отсутствие комментариев, большое количество «мертвого кода», «белые пятна» - код, про который никто не знает, что он делает и какую задачу решает, отсутствие юнит-тестов)
  • принятые решения по проекту зачастую несовместимы с отраслевыми стандартами или предлагают их неустойчивую альтернативную реализацию («велосипед»); при этом распространен аргумент «мы сделаем лучше, и ни от кого не будем зависеть» - почему-то предполагается, что собственная разработка будет блистать остроумными решениями и безукоризненным качеством; а выбор делается необоснованно, без учета рисков.
Прочее:
  • отсутствие политики ведения кода и документов (проявляется как мусор в комментариях к check-in, большое количество закомментированного кода, попадания в trunk откровенно плохого кода);
  • отсутствие специализации разработчиков; как следствие, отсутствие персональной ответственности (все в ответе за все, в итоге – никто конкретно ни за что не отвечает, т.к. уверен, что спрашивать будут не с него – как по времени, так и по результатам).
  • неконструктивные, искусственно навязанные ограничения из-за низкого проф. уровня разработчиков. Как пример, введение COP ("компонентно-ориентированный подход"). Здесь мое мнение выражается следующим образом: подходы к созданию ПО эволюционировали так – процедурный, модульный, ООП, компонентный (COM), сервисный (SOA). Переход на следующий уровень должен быть вызван эволюцией знаний на предыдущем, а не вынуждаться неспособностью справиться со сложностями предыдущего уровня. Как я понимаю, COP был, по большому счету, введен, потому что программистов не удалось заставить «побороть» ПО на уровне ООП.
  • «затянутые» ежедневные митинги; излишняя детализация и «скачки» по уровням абстракции на митингах; проявление - обсуждаются части системы и тут же рассказывают, какими булевскими переменными что-то решают; это удлиняет митинг, не добавляя ему пользы.
Анализ результатов проведенного аудита: вероятные причины негативных моментов, попытка конструктивной критики

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

Системные:
  • отсутствие систематичности в управлении качеством создаваемого ПО на всех этапах, а именно
  • отсутствие схемы сбора и управления требованиями; в том числе отсутствие систем управления customer expectations и business rules; [no-reqs]
  • проблемы политик коллективного владения кодом (code review, performance review, политики использования SCM). [no-code]
  • отсутствие схемы долговременного планирования ресурсов; [no-plan]
  • отсутствие контроля деятельности разработчиков. [no-ctrl]
Персональные:
  • отсутствие навыков работы в команде и всё, что из этого проистекает – роли, ответственность, коллективное владение кодом (проявление – даже форматирование кода в VS2005 настроено у всех по-разному); [no-cmd]
  • недостаточный уровень понимания ООА/ООД/ООП, в том числе обработки ошибок в рамках ООП (исключений, разницы между checked и unchecked исключениями), недостаточно ясное понимание понятий транзакционности и контекста исполнения, разделения обязанностей (concern separations) в коде; [no-oop]
  • низкий уровень качества кодирования в рамках декомпозиции конкретной задачи; [coding]
  • низкий уровень знаний о платформе разработке (как пример, вопрос – какие операции MSIL могут бросить OutOfMemoryException? И что с ним делать?) [no-know]
  • крайне недостаточные навыки тестирования и юнит-тестирования кода; [no-tools]
  • недостаточные навыки работы c системами SCM; [no-scm]
  • недостаточные навыки планирования рабочего времени (я про себя в первую очередь) и оценок затрат ресурсов. [no-time]
Видение и возможная оптимизация процесса разработки (если получится ):
  • Мое видение ключевых особенностей командной разработки заключается в следующем:
  • Отсутствие грамотной практики, понимания процесса командной игры и «специализма» невозможно прикрыть ничем – ни оптимизмом, ни введением особых моделей разработки; отсюда - необходимо стараться постигать и вводить успешные, зарекомендовавшие себя практики взаимодействия; не делать хитро, а делать понятно для остальных.
  • «Дьявол кроется в деталях», а именно – неважных для процесса разработки вещей, на которые можно «забить», нет, следует всему уделять внимание.
  • Коллективная ответственность, но не в форме «спихнуть на следующего»; имеется в виду, что если один из разработчиков «набыдлокодил», то команда ответственна за исправление этого.
Предлагаемые практики, в целом, направлены на устранение замечаний – как персональных, так и системных. В скобках указаны референсы на основные источники проблем, которые, как мне кажется, устраняет практика.

Коллективные:
  • внедрение схемы управления качеством ПО с использованием соответствующих инструментов; [no-reqs], [no-ctrl]
  • внедрение схемы управления требованиями к ПО и бизнес-правилами; [no-reqs], [no-tools]
  • повышение навыка коллективного владения кодом, введение code review и performance review; [no-cmd], [no-code],
  • внедрение долгосрочного планирования, разделение планирования на долгосрочное и краткосрочное, введение микропланирования и «спринтов» разработки; повышение дискретности планов до 1 часа [no-time], [no-ctrl]
  • специализация разработчиков, нежесткое выделение «кодеров» и «архитекторов», со сменой ролей после нескольких спринтов; [no-cmd], [no-op], [coding], [no-know];
  • назначение персональной зоны ответственности в проекте с периодической ротацией [no-cmd], [no-op], [coding], [no-know];
  • уменьшение митингов до 30 минут максимум, в дальнейшем – до 15 минут; [no-plan], [no-ctrl]
  • введение практики коллективного обсуждения принятых решений по архитектуре и, возможно, реализации; вероятно, можно для этого организовывать специальный получасовой или часовой митинг на время, сэкономленное за счет уменьшения утренних переговоров; [no-cmd], [no-ctrl], [no-plan]
  • разделение на задачи проводить по функциональному признаку (например, давать задачу разработчику реализовывать не отдельную фичу, а определенный слой функционала, тесно взаимодействующего с функционалом других разработчиков – через интерфейсы и т.д.) [no-cmd], [no-plan]
  • смена разработчиков между задачами, подключение и отключение разработчиков «на лету» [no-cmd], [no-plan]
  • периодическая оценка эффективности и критика всей системы (например, голосованием);
Персональные:
  • повышение профессионального уровня разработчиков; [coding], [no-oop], [no-know]
  • изучение best practices, как свободно доступных (design patterns, integration patterns), так и проприетарных (например, от MS); использование распространенных нотаций (UML, use-cases) [no-oop], [no-code], [coding]
  • развитие/привитие навыка code review, performance review, в том числе самостоятельного – важно уметь смотреть на свой код критически; [no-time], [no-code], [coding]
  • повышение навыков работы с инструментальными средствами планирования, проектирования, тестирования, юнит-тестирования; [no-tools], [no-time];
  • развитие навыков оценивать риски, ресурсоемкость задач [no-ctrl,no-time].
P.S. Все, можете кидаться помидорами

20 Ноябрь 2008 г.

В предверии

Как гласит китайская поговорка: с одной стороны, смутное время - это опасность, с другой стороны – возможность. Жаль только, что простой IT-шник (например, я) вряд ли сможет этим воспользоваться.

По поводу прозрачности финансов - предлагаю организовать (хотя бы в интернете) табло, показывающее текущие запасы золотовалютных резервов в России. Чтобы не было разногласий в цифрах в связи с плавающими курсами, использовать би- или мультивалюту. Заранее вижу успех и простоту сопровождения, потому что дополнительные разряды приделывать не нужно - скорее снимать (*грустный смех за кадром*).

18 Ноябрь 2008 г.

Мои 50 копеек к вопросу о финансовом кризисе.

Не сдержался и запостил. На воре и шапка горит, как говорится.
"Воровство из бюджета уже не актуально". Так заявил LIFE.RU председатель Счетной палаты после того, как отчитался о работе своего ведомства перед членами Федерального Собрания.

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

В прошлом году Счетная палаты выявила финансовых нарушений в среде чиновников на 140 миллиардов рублей. Нецелевое использование бюджетных средств, по данным ведомства Степашина, составило 1 миллиард, в то время как Росфиннадзор, проведя параллельный мониторинг, называет другую цифру - 2 миллиарда рублей.
Конечно, уже неважно, кто сколько взял :) Тем более, что называется это теперь "бюджетные программы". Тем более, что времена уже не те, да и брать становится неоткуда. Кстати, обратите внимание на расхождение в 1 миллиард. руб. "Неплохая работа" ведомства, что сказать.

Я обожаю этих людей.