Friday 11 November 2011

Доска для архитектора

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

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

Более того, доска (являясь, по сути, большим листом бумаги) представляет собой примитивный, но очень действенный "усилитель интеллекта" (Станислав Лем "Сумма Технологий"). Автор искренне надеется читатель лишен приобретенной ненависти к прямоугольным формам и понимает их полезность.

Итак, рынок изобилует разнообразными маркерными досками, но некоторые люди (к которым автор причисляет и себя) находятся в активном поиске альтернатив. Стоит признать, начальным мотивирующим фактором является стоимость фабричной доски.

Сформулируем основные требования:
  1. Разумная стоимость
  2. Долговечность
  3. Возможность создания детализированных схем
  4. Контрастность
  5. Не маркость
  6. Субъективное удовольствие от использования
  7. Оригинальный вид (опционально)
Многие используют доску для создания исключительно грубых и примитивных схем, но иногда, если обсуждаемый проект сложен и предполагается его дальнейшее обсуждение, куда эффективнее аккуратно указать необходимые детали или оставить место для них.

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

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

Маркерная доска v1.0

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


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

Минус, кстати, заключается опять же в данной особенности. Когда "шедевр" нужно убрать -- необходимо использовать специальные средства:
  1. мистер мускул или аналоги (коллеги не будут рады, помещение требует проветривания)
  2. спиртовой раствор или водку (коллеги вас не поймут, начальство уличит всю команду в злоупотреблении алкоголем)
  3. одеколон (коллеги озвереют, начальство постарается вычислить местного "мачо")
  4. специальные салфетки (предположительно, довольны будут все, но не ваш кошелек)
Домашняя доска была водружена на место в 2005 году и находится там по сей день. Никакого ухудшения ее качеств не замечено. Попытка несанкционированной уборки, которая была нацелена на уничтожение без сомнения ценных наработок автора, успехом не увенчалась -- с доски была смыта только эфемерная пыль.

Маркерная доска v2.0

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

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


Любопытному читателю, вероятно, уже известен термин blueprint, применимый, по сути, к любому детальному плану. Автор решил что для проектирования архитектуры (architecture blueprinting) необходим соответствующий инструмент, который и был создан с использованием уже известной технологии.

Потребовалось всего несколько листов цветного картона (цвет, кстати, подбирался очень аккуратно при участии внимательного и очень вдумчивого дизайнера, Leo спасибо) и стандартная стеклянная рама для получения необходимого результата.

Технология изготовления "магической доски":

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


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

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

Кому что, разработчику подавай квадратики, ну а дизайнер просто резвится:


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


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

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


Описываемые события имели место в конце 2006 года. Кстати, используя данный подход легко получить:
  1. корпоративную доску
  2. доску с фоном любимого цвета
  3. лесную или небесную доску
  4. т.д.
Достаточно выбрать необходимый цвет:

Ребрендинг или приход новой "власти" такая доска переживет легко и непринужденно.

Маркерная доска v3.0
Автор иногда думает о третьей, еще более приятной и удобной, версии маркерной доски. Какой она будет? Полностью прозрачной, мобильной, со встроенной подсветкой, со встроенной блендой? Кто знает, поживем -- увидим.   

Полезные ссылки

Версионная миграция структуры БД: почему так лучше не делать

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

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

 Оценка сложности проекта

Краткое содержание
Постараюсь кратко сформулировать все замечания, предположения и выводы для облегчения последующей дискуссии:
  1. Современный процесс разработки ориентирован на короткие итерации, частые билды и постоянную интеграцию
  2. Инкрементальные изменения структуры баз данных весьма дороги, ввиду явных ограничений СУБД
  3. На ранних этапах разработки ограничения СУБД не всегда очевидны/интересны (показано ниже)
  4. Успешный продукт сталкивается с большинством проблем достигнув значительных размеров, именно тогда стоимость исправления многих проблем огромна
  5. Выбор способа хранения и обработки данных определяет архитектуру приложения
  6. Внесение значительных изменений в архитектуру на поздних стадиях является очень дорогим удовольствием
  7. Именно на поздних стадиях разработки процесс пытаются ускорить ввиду явных преимуществ с точки зрения бизнеса и прибыльности
  8. Изменения структуры базы данных часто влекут за собой дополнительную обработку/преобразование хранимых данных
  9. На поздних стадиях любые изменения структуры базы данных, ввиду многих ограничений СУБД, являются проблематичными.
  10. Для многих проектов, версионная миграция структуры БД на ранних этапах покажется очевидным решением, впоследствии став серьезным ограничением. Более или менее универсальный рецепт — необходимо избегать частого изменения структуры базы данных.
Еще один пример  

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

В финальный релиз может войти множество изменений структуры БД (зачастую исключающих друг друга), обеспечивая потрясающе медленный апгрейд на стороне клиента, что, в свою очередь, может привести к недовольству с его стороны, поскольку независимо от реального предназначения системы, время вынужденного бездействия является очень критичным фактором. Другими словами, процесс разработки может не быть идеальным, требовать дополнительное время на решение разнообразных проблем с миграцией, но для клиента все должно пройти максимально быстро, без каких-либо проблем и вмешательств извне. Коротко:
  • интенсивная разработка -- частые сборки и частые изменения структуры БД
  • разработчики не работают в изоляции -- помните о тестерах и зависимых разработчиках
  • на любом этапе миграции могут возникнуть проблемы
  • очень часто проблемы миграции сложно выявить сразу
  • "битая база" всегда приводит к временным затратам
  • клиент, ждущий несколько часов пока база "обновится", расстроится или даже разозлится
  • поломка у клиента означает на несколько порядков больше проблем и времени необходимого для их решения
Пример первый, система живущая 14 лет
Основная решаемая проблема -- управление средним количеством сетевых устройств нескольких типов. Размер реальных установок варьировался от 1 до 60 устройств. От системы устройства получают конфигурацию и управляющие команды, отправляя в ответ подтверждения, разнообразную статистику и "телеметрию". Также система реализует пользовательский интерфейс для редактирования разнообразной конфигурации устройств.

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

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

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

 Обновление структуры

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

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

Технические нюансы
Изменение существующих таблиц, используя ALTER TABLE, скорее всего, не будет дешевой операцией. Автор заранее опускает идеальные варианты, которые сводятся к изменению метаданных таблицы, предлагая читателю задуматься над индексами, которые могут существовать, над необходимостью преобразования данных, над физическим размещением данных на диске и отличием идеализированного табличного представления от реального размещения данных и соответствующих проблем с производительностью. Кстати, часто вы можете встретить призыв не использовать ALTER TABLE, отдав предпочтение copy-rename процедуре (например:Don’t Alter Table. Do Copy and Rename) Для преобразование данных не самой тривиальной сложности, в любом случае, придется использовать дополнительную логику, реализованную на каком-либо языке программирования.  

Решение
На данном этапе светлые головы компании решили полностью избавиться от необходимости менять структуру базы данных и хранить конфигурацию устройств в очень модном (только начал набирать популярность) XML формате. Согласитесь, очень удобно: десериализуем XML в дерево объектов, работаем с ними, затем сериализуем обратно в XML и сохраняем в базу. Естественно, в базе появляется BLOB, но после недолгих колебаний было решено оставить эту проблему базе данных. Для преобразования данных использовались небольшие независимые программы (изначально perl скрипты, затем логика на java), которые обеспечивали последовательное преобразование базы данных, скажем, от версии X до версии Y.


Упрощение обновления базы данных

Эффект
Поскольку добавление нового функционала (новых опций) сводилось к изменению XML представления -- изменения структуры базы данных свелись к нулю, существенно упростив процесс (по крайней мере, с точки зрения работы с БД). Процесс разработки ускорился, поскольку появилась возможность работать с более сложными структурами данных, не заботясь практически ни о чем. Появилась возможность сохранять историю (достаточно сохранить несколько XML) и т.д.
 
Хронология: становление
После значительной переработки способа хранения конфигурации, развитие системы ускорилось и количество проблем, на первый взгляд, уменьшилось. Компания выпустила новую версию, которая при установке преобразовывала старую базу в новый формат, в очередной раз тратя время клиентов без видимой причины, но обещая избавить их от всех бед в будущем. Клиенты верили и терпели. Затем последовали новые версии, которые расширяли функционал системы и решали проблемы предыдущих. Переход на более новую версию системы занимал от 15 до 30 минут, что выглядело очень серьезным достижением. Но так было недолго. Наращивание функционала привело к взрывному росту хранимых данных.

Далеко не самую последнюю роль в этом сыграла относительная дешевизна изменения конфигурации. Разработчики выбирали самый простой способ реализации совершенно не заботясь о будущем. Результатом такого подхода явились горы XML кода и большое количество необходимых преобразований при переходе к каждой последующей версии. На данном этапе, для перехода базы данных из состояния X.1 до состояния X.2 (добавлен новый функционал) необходимо было выполнить одно или несколько преобразований над хранившимися в базе XML представлениями конфигурации. Только после успешного выполнения таких преобразований система могла начать работу (обновленный код мог десериализовать сохраненное представление).
 
Проблемы на данном этапе
Преобразования конфигурации представляли собой набор последовательных трансформаций сохраненных XML файлов (в базе действительно хранились xml файлы, которые на ранних этапах даже были полостью совместимы с устройствами). Часть таких преобразований трактовала XML представление как строку и использовала обычную замену. Другие программисты предпочитали работать с DOM деревом или писать «оптимизированные» варианты, используя SAX парсеры.

Подобного рода преобразования были независимы и, например, наличие их большого количества в релизе, могло означать необходимость выполнить несколько преобразований для одного типа конфигурации, каждое из которых самостоятельно выполняло десериализацию в DOM дерево, изменение дерева и последующую сериализацию, повторяя, таким образом, ресурсоемкие и совершенно необязательные шаги несколько раз. У разработчиков данная операция занимала незначительное время, ввиду исключительно небольшого размера тестовых данных, используемых во время разработки. Размер реальной конфигурации, хранимой реальными системами, был на несколько порядков больше (от 100 килобайт до 1-2 мегабайт, при общем размере базы до 1-2 Гб). Переход на новую версию системы, в очередной раз, стал большой проблемой для клиентов.


 Ошибка во время обновления

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

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

 Успешное обновление

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

Проблемы на данном этапе
На данном этапе, была поставлена задача решить проблему длительного обновления при переходе на новую версию, упорядочить логику обновления базы данных и упростить работу других команд, которым, к слову, все еще приходилось тратить значительное время на правку и отлавливание разнообразных багов связанных с преобразованной конфигурацией. Кроме того, некоторым, особенно активным, клиентам удалось довести размер конфигурации до 10 мегабайт и общий размер базы до 5 гигабайт, после чего, они столкнулись с новым классом очень интересных проблем. Завершить картину, можно желанием руководства получить систему, совместимую с устройствами предыдущих версий. Все время устройства и система управления развивались синхронно. Пример: Система.1 отправляла конфигурацию на Устройство.1, Система.2 на Устройство.2 и т.д. Была поставлена задача обеспечить возможность для Системы.4 отправить правильную конфигурацию на Устройства.2,3,4. Отличия, к слову, зачастую были очень существенными.
 
Решение
Для написания логики по преобразованию конфигурации, был реализован специальный механизм, который, помимо всего прочего, умел проверять корректность производимых изменений на каждом этапе, предотвращая, таким образом, появление битых баз. Автоматизированная система тестирования и верификации всего продукта делала свое дело, выявляя даже скрытые и местами возможные только в теории проблемы. Конфигурацию начали хранить в архивированном виде, решая как проблему размера, так и проблему скорости чтения и преобразования (производительность процессоров растет, а вот дисковая подсистема как была страшным тормозом, так им и осталась.

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

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

Заключение
Автор получил данный проект в достаточно плачевном состоянии. Вместе с проектом досталось несколько сотен багов, реальные клиенты и множество запросов на дополнительную функциональность, включая страшный запрос на систему с обратной совместимостью и адаптацию всего хозяйства под новомодный Agile. Кстати, реализация непрерывной интеграции (continuous integration) для существующего уже длительное время большого проекта и проверка всего, что только можно проверить после каждого комита — отдельная и очень интересная тема. С задачей удалось справиться, исключительно благодаря отличной команде и безграничному оптимизму. Множество ошибок было исправлено:

 Исправленные ошибки

Процес разработки был достаточно интенсивным:

 Публичные сборки

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

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