Яков Сироткин (yakov_sirotkin) wrote,
Яков Сироткин
yakov_sirotkin

Что я делал на прошлой работе

На прошлой работе я больше 3 лет занимался одним проектом, пришло время рассказать об этом подробней, пока ещё что-то помню. Мы занимались довольно древним корпоративным приложением, которое досталось нам в плачевном состоянии. Несмотря на то, что корпоративным стандартом был IE 9, в коде встречались проверки на NN3 и IE4. И был один крайне неприятный баг: если неудачно пошевелить мышкой над меню во время загрузки страницы, то страница могла зависнуть и нужно было начинать всё с начала. Я посмотрел на код, увидел, что поправить его малой кровью не удастся, нужно переписывать с нуля, нашел в Интернете решение для меню и переписал. Оказалось, что вопрос уже исследовали до меня и все знали, что меню нужно полностью переписать, но не было сил внести это в планы.

Весь UI в целом был сделан на самописной библиотеке на базе Struts, поэтому при каждом клике на элемент формы происходила полная перезагрузка страницы, которая могла занимать минуту, а полей в формах было предостаточно. Вдобавок, все данные хранились в сессии и когда пользователи открывали приложения сразу в двух вкладках, то начинались большие проблемы. Все остальные проекты, которые использовали эту библиотеку уже давно умерли. Я со своей стороны насаждал jQuery, статический html и получение json от сервера. Однако, приложение было довольно большое и основной конфигурационный xml для этой библиотеки содержал около 4 тысяч строк. По мере перехода на новые технологии я выписывал на доску оставшееся число строк вместе с датой и все могли видеть прогресс. За 3 с лишним года наша команда полностью избавилась от этой сторонней зависимости, перед увольнением я целенаправленно добил оставшиеся одиночные страницы.

Вместе с избавлением от страшной библиотеки, мы отказались сначала от самописных JSTL-тэгов, а потом и от JSP вообще. Кроме этого мы внедрили популярные библиотеки для таблиц и графиков, перешли на IE 11. Нужно сказать, что UI мы переделывали постоянно и вроде как исследование показало, что пользователи считают наше приложение самым удобным во всей корпорации. Но это уже не моя заслуга, я больше занимался техническим долгом, красиво делали коллеги.

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

Конечно, самым впечатляющим достижением нашей команды была победа над PL/SQL. У нас было написано на нем очень много логики, в которой было очень тяжело разбираться, но это ещё не самое страшное. У нас был сторонний сервис, который мы вызвали через хранимые процедуры на соседней базе глубоко изнутри наших хранимых процедур. И этот сервис делал коммит внутри себя, вместе с успевшей отработать нашей логикой. Периодически случался таймаут, транзакция откатывалась, но только частично. В результате данные наших пользователей превращались в мусор и это было очень больно. Из всех клиентов этого сервиса в живых остались только мы, поэтому компания решила отказаться от его использования и нам сказали перейти на другой продукт, работающий как веб-сервис. Поэтому у нас появилась достаточная мотивация, чтобы переписать наш PL/SQL на Java. Как мы это сделали можно узнать из моего рассказа на JPoint 2015.

Я только немного расскажу о самой страшной процедуре в 1000 строк. Основная наша задача нашей системы была в том, чтобы хранить информацию об очень сложных контрактах, для контрактов придумали примерно 50 разных статусов, из ни около 20 реально использовались. И в интерфейсе можно было выбрать следующий статус из списка, а этот список получался как запрос к табличке, в которой хранились возможные переходы из одного статуса в другой. Казалось бы, всё элементарно, но на этот маленький запрос накрутилась вся бизнес-логика приложения, все ограничения и требования дополнительного контроля. Получилась тысяча строк на PL/SQL, которая вышла из под контроля. Почему Вася не может перевести эту транзакцию в этот статус? Как объяснить аудиторам, почему эта транзакция перешла в такой статус без одобрения вышестоящего менеджера? Эти production issues сыпались на нас пачками, отнимали кучу времени и нервов и у нас, и у пользователей. При переписывании на Java я поменял логику — теперь для каждого статуса был специальный метод, который определял, может ли перейти в него данная транзакция. Более того, для каждого статуса я сделал отдельную страницу в wiki со спецификацией, когда транзакция может перейти в этот статус. Потом эта спецификация поддерживалась в актуальном состоянии, QA тестировал наше приложение на соответствие спецификации и все вопросы стали решаться на уровне чтения спецификации, без исследования кода. И проблемы практически сошли на нет, потому что логика стала понятной и предсказуемой, спорные моменты были выявлены и по ним были приняты решения.

Ещё одной важной вехой в борьбе с PL/SQL было переписывание экспорта XML-документов в другую систему. Изначально было 10 XML-шаблонов, которые лежали в специальной таблице, разбитой на строки. Данные сначала готовились отдельной таблице, а потом делался страшный запрос, который выдавал строчки итогового XML-документа. И всё это было реализовано при помощи 5000 строк PL/SQL. У меня получился один XML-шаблон в виде файла и 1000 строчек кода на Java. Если раньше любое изменение в PL/SQL занимало неделю мучений опытного разработчика, то теперь изменения стали вноситься за минуты. И мы потом внесли очень много изменений, вряд ли кто-то смог бы их сделать при старом подходе.

Кроме PL/SQL мы удалили из базы и много других ненужных объектов: неиспользуемые колонки, функции, таблицы, view. Почистили базу от записей, которые когда-то оказались в экзотических статусах, от использования которых потом отказались. Несколько релизов подряд мы удалял объекты десятками. Это помогло сделать нашу систему гораздо понятней.

Нет ничего удивительного, что нашлось применение для асинхронной обработки задач. Начал я с посылки писем пользователям — раньше это делал job в Oracle, а мне как раз нужно было над чем-то работать во время дежурства на рождественских каникулах. Внезапно оказалось, что это было очень полезное для пользователей изменение: раньше письма ходили раз в 10 минут и за это время пользователи успевали созвониться, а теперь письма стали приходить сразу. И, конечно, содержание писем заодно доработали. После этого мы сделали новый движок для отчётов: у нас уже было специальное приложение, но для него нужно было поддерживать пачку view и конфигурировать столбцы отчётов через редактирование специальной таблицы. Вместо этого мы сделали широкую таблицу, в которую заносятся все нужные данные. Каждый раз, когда какая-то запись меняется, создается задача для обновления данных. Можно перегенерировать все данные, если создать задачи для всех записей, это делается при добавлении новых параметров или при изменении логики их вычисления.

Кроме этого мы стали культурно записывать историю изменений, заменили древние EJB на веб-сервис и, конечно, реализовали очень много новой бизнес-логики. Я довольно долго был не только разработчиком, но ещё и замещал должность Scrum Master. Первое что я сделал в этой роли — wiki страница с текущим статусом проекта, после этого продолжительность еженедельных митингов с начальством сократилась с получаса минимум до 5-10 минут. И все знали, какой у нас статус, какие проблемы, когда релиз и куда звонить по срочным вопросам. Если раньше каждый релиз включал в себя 5-7 пунктов, которые делались через боль и страдание, с выкидыванием планировавшейся функциональности, с баг-репортами после пользовательского тестирования и хотфиксами после выкладки, то в итоге мы стали делать новые релизы с десятками новых фич без единого замечания от пользователей. Это произошло благодаря QA-отделу, который мы создали у себя в команде вместо индийских тестировщиков. Наши QA постепенно покрыли проект автоматически тестами и даже наш Product Owner перестала находить баги. Ещё у нас в компании была проблема, что новые люди получали доступ к проекту через месяц-два после найма, поэтому их бросали на какую-нибудь внутреннюю ерунду. Мы своих ребят не отдавали, честно объясняли ситуацию, бросали на изучение Java и в нужный момент получали уже подготовленных специалистов, хотя часто набирали людей с не очень большим опытом. Ещё я вроде как договорился, что всех сотрудников надо раз в год посылать в командировку в Цюрих, но своими глазами я этого уже не увидел, так что не знаю, как это работает на практике.

Должен признать, что одну большую проблему я за всё время работы так и не заметил. Мы разрабатывали на WebSphere, у нас была длинная инструкция, как её настраивать и мы по ней работали. При этом деплоймент у нас длился минуту и больше, спасала только перезагрузка классов из IntelliJ IDEA в режиме дебага. Однако, когда наш деплоймент почистили от многочисленных библиотек, которые грузились по несколько раз, деплоймент стал работать в разы быстрее! Если бы я сделал это сразу, то это сэкономило бы нам очень много времени.

С тем опытом, который я получил за последний год, я бы, конечно, попытался сделать веб-сервисы при помощи аннотаций, а не обычными сервлетами. Но это уже другая история не знаю, куда там дальше будут уходить с WebSphere и Java 6.
Tags: hr
Subscribe
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 5 comments