Как привести в порядок проект после 3 других команд


Автор
Алексей
Алексей
Ведущий разработчик, архитектор

В статье мы описываем проблемы, с которыми столкнулись на проекте, который нам достался от 3 других команд, и как мы их решали.

Суть проекта

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

Происходит движение по логике: аудио - транскрибирование - подтверждение - рассылка.

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

Есть обязательное условие: данные не могут потеряться. Поэтому на локальной машине пользователя все хранится в базе данных MySQL. Данные синхронизируются с основным сервером.

Специфика проекта

  • Система и ее заказчик находятся в Европе;
  • Система работает в более чем 10 клиниках, каждая из которых имеет уникальную специфику работы;
  • Чтобы уговорить клинику на новую версию, требуется много времени: сначала развернуть на тестовый сервер клиники, они тестируют в течение 3х недель, потом разворачиваем на живой сервер;
  • В базах данных находится конфиденциальная информация о пациентах, поэтому у каждой клиники свой сервер.

Что мы унаследовали

  1. Примерно 400 000 строк исходного кода на C# (+ еще несколько внешних библиотек). Часть исходных кодов была потеряна;
  2. На начало нашей работы в неделю обрабатывалось 5000 работ (прохождение по всем необходимым стадиям, выполнение взаимодействия со всеми внешними сервисами и т.д.);
  3. Отсутствие документации;
  4. Отсутствие тестов и тестовых данных;
  5. Отсутствие человека со стороны заказчика, который знал бы все о системе (человека, который был бы с момента создания проекта);
  6. Код был написан так, что покрывать его unit тестами было невозможно;
  7. База данных MS SQL состояла примерно из 120 таблиц;
  8. Проблемы с производительностью;
  9. Использование ADO.NET, Dapper, LINQ, Entity Framework 4.

Часть архитектуры приложения

15-1.png
Архитектура приложения.

  • Desktop client – рабочее приложение доктора, большинство функций системы выполняется на нем;
  • Desktop Client Service – сервис, который используют все Desktop Clients;
  • Task Scheduler – модуль системы, который отвечает за перевод работ на следующую стадию и другие периодические операции;
  • iPad App iOS – приложение для докторов на iPad;
  • Web Admin – web часть для настройки рабочих процессов, прав доступа к устройствам и т.д.;
  • Web Client — web часть для докторов, которая имеет ограниченный список возможных функций.

Основные достижения за 1,5 года

  1. Производительность приложения возросла в 10 раз;
  2. Количество одновременных пользователей увеличилось в 5 раз;
  3. Количество обрабатываемых работ в неделю достигло 30 000;
  4. Заказчик начал доверять нашим решениям.

Как мы этого добились.

1 проблема: конфиденциальность данных

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

Мы написали программу анонимизации, которая заменяет все буквы в документах на единицы, а содержимое аудио - на массив из нулей. Получается вместо John Smith - Name1. Ее разработка заняла 3 дня. После этого мы скопировали живую базу данных, которая подверглась анонимизации.

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

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

2 проблема: код не для тестирования

Унаследованный код, который надо расширять не поломав? Что может быть проще: использовать unit тесты и радоваться жизни. Но качество унаследованного кода было низкое, а сам код был написан с использованием синглтонов и старой Entity Framework, которая не подходит для тестирования. Но тесты были необходимы. И мы выбрали путь создания интеграционных тестов. Новые фичи старались писать так, чтобы покрыть их unit-тестами.

Утилита и функция восстановления базы данных
До этого программисту надо было запустить программу, утилиту сохранения данных, вызвать в начале теста восстановление базы данных с указанием пути к восстановленным данным. Утилита сохранения данных проходила по всем таблицам, которые есть в базе данных, и сохраняла данные из них в XML. После этого функция восстановления создавала новую базу данных, восстанавливала данные в ней и изменяла строки подключения так, чтобы тесты видели новую базу данных. Для восстановления данных использовали формирование команды вставки и использование ADO.NET для выполнения команды. Это дало нам независимость от Entity Framework. Как положительное следствие – теперь эту утилиту легко перенести на любой другой язык.

Если правильно подготовить базу данных, восстановление занимает 1 секунду. С учетом того, что в CI были ночные тесты, это была приемлемая величина.

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


15-1.png
Команда специалистов по тестированию за 3 года выросла до 5 человек.

Выводы

  1. Неизбежно изобретать маленькие велосипеды для унаследованного кода;
  2. Если вы думаете об интеграционных тестах, сразу думайте о ночных тестах;
  3. Восстановление базы данных может быть очень удобно в плане симуляции данных;
  4. Не надо хранить данные для восстановления базы данных в проекте тестов. Лучше выкинуть их в zip архиве на Dropbox, а в архиве хранить ссылку на них;
  5. Положительным побочным эффектом восстановления оказалась проверка корректности изменения структуры баз данных, которую нам периодически приходится делать.

3 проблема: счетчики производительности на целевой машине

Вопрос, который у нас возник в течение первого года: как показать состояние унаследованной системы и то, что она постепенно не выдерживает нагрузок? Эффективное средство – собирать счетчики производительности раз в неделю. Счетчиков реально много, они дают графики, их можно экспортировать в Excel, производить анализ и т.д. Жаль, что мы не делали это с самого начала, когда было 5000 работ в неделю.

Плюс подхода
Заказчика легко уговорить – это встроенная возможность Windows, поэтому уговаривать даже почти не пришлось на запуск сбора статистики.

Выводы по проблеме
Надо было снять счетчики производительности в самом начале проекта. Хотя и сейчас сравнивать их с интервалом раз в месяц довольно интересно.

4 проблема: не доверяйте конвертерам из RTF в HTML

В унаследованном коде документы хранились в формате RTF. Заказчик попросил доработать возможность редактирования документов в web клиенте. Была лицензия на TxTextControl v 19, поэтому редактор сделали с использованием этого компонента. Позже выяснилось, что форматирование из RTF в HTML и обратно приводит к проблемам: шрифт сбивается с 10-го на 10,5, абзацы с отступами хромают и т.д. Служба поддержки рекомендовала обновиться до 20й версии. При подробном исследовании оказалось, что в 20й версии есть масса других сложностей.

Выводы по проблеме

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

5 проблема: восстановление потерянной части для iOS

Кроме веб части существует приложение для iPad. Исходные коды от него были потеряны. После некоторых поисков мы попробовали восстановить исходные коды с помощью декомпиляции. Это можно сделать с помощью Developer Bundle от RedGate, в состав которого входит Ants Profiler. В целом качество декомпиляции хорошее: после анализа мы в течение 2х часов нашли, как происходила аутентификация для iOS в WCF сервере и восстановили её в последней версии программы.

Выводы по проблеме
Developer Bundle от RedGate реально нас выручил.

6 проблема: профилировщик

Мы столкнулись с проблемой производительности: через 40 минут работы на клиенте начинались задержки при печати. Мы проверили все, что можно с точки зрения сервера, но ничего плохого не нашли. К тому времени мы решили попробовать Ants Profiler.

Преимущества Ants Profiler:

  1. Легкий в использовании, но требует администраторских прав на установку на локальной машине. Запустить под ним программу можно в 3 клика;
  2. Триальный полнофункциональный период в 14 дней. Если надо разово запустить на конечной машине - самый подходящий выбор;
  3. Наглядные отчеты;
  4. Может логировать SQL запросы, обращения к диску, сетевые запросы.

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

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

Вывод по проблеме
Найти нужный уровень детализации в Ants Profiler.

7 проблема: производительность Базы данных на уровне снапшотов

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

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

После недельного анализа мы попробовали перевести базу данных в snapshot mode. Это дало отличные результаты: очередь с 400 сократилась до 12 работ, а это в пределах нормы.

Выводы по проблеме
В дополнение к созданию индексов не надо забывать о механизме снапшотов, который есть в MS SQL.

8 проблема: отчеты

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

Консольная утилита
Для решения мы создали консольную утилиту и поставили её на выполнение с помощью планировщика задач Windows, а из админки убрали. Таким образом, мы сохранили логику - к началу рабочего дня отчет готов.

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

15-1.png

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

Почувствуйте наш подход и повторите
успех наших клиентов

Напишите нам
АЛЕКСАНДР НОСКОВ
АЛЕКСАНДР НОСКОВ
СЕРГЕЙ ИСАКОВ
СЕРГЕЙ ИСАКОВ