SlideShare a Scribd company logo
Поэтапный 
рефакторинг: 
success story
Алексей Машанов
Цели рефакторинга
●   Упрощение добавления новых возможностей за счет
    возможности реиспользования кода.
●   Упрощение сопровождения кода за счет приведения его в
    человекочитаемый вид, нормализации кода и структуры базы.
●   Избавление от велосипедов и перенос тем самым головной
    боли по их развитию и поддержке на сообщество.
Характеристики системы
●   Perl + PostgreSQL
●   ~ 1200 модулей и 400 скриптов
●   ~ 300000 строк чистого кода
●   ~ 450 таблиц в БД
●   ~ 150 хранимых процедур и 140
    триггеров
Разбиение на этапы
                    Этап рефакторинга —      коммит
                    должен укладываться 
                    в рамки одного релиза

                                                              t

    Релиз (3­4 недели)              Шаг рефакторинга — 
                                    изменение не сказывающееся 
                                    на работоспособности системы

Рефакторинг выполняется в основной ветке разработки
Test Driven Refactioring
      Для каждого вносимого в код изменения


               Написание автотеста


Проверка автотеста путем поломки тестируемого кода


       Внесение модификации (рефакторинг)


   Проверка модифицированного кода автотестом
Структура автотестов
                                              Test::Class


                                               My::Test       rollback после 
lib/                      t/lib/
                                                              каждого теста

  Class1                       Class1::Test

  Class2   Class2::Sub1        Class2::Test                 Class2::Sub1::Test

  Class3   Class2::Sub2        Class3::Test                 Class2::Sub2::Test
I. Замена самописных ORM
       на DBIx::Class
Структура до рефакторинга
         Ent           Ent::Smth11               Entity     Entity::Smth11
new()                                   new()
                       Ent::Smth12                          Entity::Smth12
list()                                  list()
get()                     …             get()                    …
set()                                   set()
save()                Ent::Smth1N       save()              Entity::Smth1N

●   Два примерно одинаковых ORM
●   Методы модификации и поиска объединены в одном классе
●   Доступ к полям объекта как к элементам хэша
Что хотим получить
DBIx::Class::Row   Schema::Result::Smth11   DBIx::Class::ResultSet   Schema::ResultSet::Smth11
new()              Schema::Result::Smth12   search()                 Schema::ResultSet::Smth12
get_column()                …                                                   …
set_column()       Schema::Result::Smth1N                            Schema::ResultSet::Smth1N
insert()
update()
                   Schema::Result::Smth21                            Schema::ResultSet::Smth21
                   Schema::Result::Smth22                            Schema::ResultSet::Smth22
                            …                                                   …
                   Schema::Result::Smth2N                            Schema::ResultSet::Smth2N

●   Один ORM
●   Методы модификации и поиска в разных классах
●   Доступ к полям объекта через акцессоры
Зачем?
●   До рефакторинга
    ●   Два самописных ORM в одной системе это слишком много
    ●   Оба из них не поддерживают отношений между таблицами, тем не менее они нам
        необходимы, что приводит к обилию в коде plain SQL запросов
    ●   Вновьприбывшие разработчики вынуждены с ними разбираться и вникать в их отличия
●   После рефакторинга
    ●   Много новых хороших возможностей, которым мы все очень рады
    ●   Мы не одни во вселенной: почти все что нам может понадобиться уже изобрели,
        реализовали, отладили и устранили почти все баги, а какие не устранили, устраняют
        довольно-таки быстро
    ●   Опыт работы с DBIx::Class разработчику пригодится не только для работы над нашей
        системой, поэтому он с большей вероятностью потрудится разобраться в нем
        поглубже
Создание схемы
           table
          table
         table
                               схема
                    DBIx::Class::Schema::Loader

                         code style conventions
                           simple perl script

                         выстраиваем нужную 
                              иерархию              Schema::Result::*


Используем статическую схему                      DBIx::Class::Schema
Схема обертки
                tiehash
         Ent               EntHash     Schema::Result::SmthX
new()                     FETCH()     get_coumn()
set()                     STORE()     set_column()
get()                     EXISTS()    has_column_loaded()
list()                    NEXTKEY()   columns()
save()                    _DBIC_      insert_or_update()
                          _DBICRS_
  Ent::SmthN
 Ent::Smth2                           Schema::ResultSet::SmthX
 dbic_class()
Ent::Smth1
dbic_class()                          search()
dbic_class()
Callback методы
DBIx::Class::Core                                        Ent::*
                                                      save()
DBIC::EntCallback                                     delete()
insert()
update()
delete()
                       да                       нет
Schema::Result::*           caller() eq 'Ent'
Неспешная миграция
1.   Ent::XXX­>...        Schema­>resultset('XXX')­>...

2.   SELECT * FROM xxx    Schema­>resultset('XXX')­>select()


3.   Ent::XXX­>save()     Schema::Result::XXX­>insert()
                          Schema::Result::XXX­>update()

     Ent::XXX­>delete()   Schema::Result::XXX­>delete()
Завершение рефакторинга
●   Удаление иерархии старых ORM
Timeline рефакторинга
                  Схема таблиц Schema::*
        Обертка Ent вокруг DBIx::Class                         1 релиз
     Callback методов

                              Перенос хуков в Избавление
      Замена Ent::* →
                              Schema::Result::* от plain SQL   N релизов
    Schema­>resultset('*')


            Удаление старого ORM                               1 релиз
t
II. Единый механизм
хранения сущностей
Исходная структура
                                            Service связан с объектом одного из трех
       Lbill             Client
                                        ●


                                            классов, а не с одним.
                                        ●   User, Server, VDS имеют примерно
                                            одинаковый набор финансовых полей, но
                                            не используют наследование.
                                        ●   Лишняя связь от User, Server, VDS к Client.
User           Server             VDS
                                        ●   Сложные запросы к базе со
                                            множественными LEFT JOIN.
                                        ●   Добавление новой сущности приводит к
                                            созданию 1 класса, 3 связей и
                                            модификации Service.
               Service
Желаемая структура
                    ●   Добавление новой сущности
Client                  приводит к добавлению 1 класса и 1
                        связи.

 Lbill      User    ●   Финансовые операции ограничены
                        работой с Entity, а не с тремя User,
                        Server, VDS.
Entity     Server
                    ●   При добавлении новой сущности
                        большинство возможностей (кроме
Service     VDS         технических) - «из коробки».
                    ●   Нет лишних связей (нормализация).
Структура базы
        vz_vds                                                                  vz_vds
      servers                            clients                               servers
   id                                                                       id
      users                         id                                         users
 id                                                                       identity_id
   client_id
id                                                                       id
                                                                          entity_id
 client_id                                lbills                            технические 
   lbill_id                                                              entity_id
client_id                                                                 технические 
 lbill_id                           id                                      поля
lbill_id
   финансовые                                                            технические 
                                                                          поля
 финансовые                         client_id                            поля
   поля
финансовые 
 поля
   технические 
поля                     services                     services                entities
 технические 
   поля
технические 
 поля                user_id                       entity_id             id
поля                 server_id                                           lbill_id
                     vz_vds_id                                           финансовые 
                                                                         поля
                  Было                                           Стало
Миграционные триггеры
entities                           AFTER UPDATE
               Обновление соответствующих финансовых полей в 
               таблицах users, servers, vz_vds при их изменении

                                   BEFORE INSERT
 vz_vds
               1.Проверка, что все синхронизируемые из entities поля IS 
servers
               NULL — это означает, что не выполняется попытка 
users
               установить их значение при INSERT
               2.Автоматическое заполнение синхронизируемых полей 
               данными из соответствующей записи в entities

                             AFTER INSERT OR UPDATE
               Проверка, что все значения полей соответствуют 
               значениям всех соответствующих полей в таблице entities
Заполнение данными
                                                            vz_vds
                                                      id   servers entity_id
            entities                               24786
                                                    id                 1
                                                           users entity_id
                                                   38798               2
1.   id                                           24786
                                                   id
                                                   78969
                                                  38798
                                                                         1
                                                                    entity_id
                                                                          3
     1                                           24786                  12
     2                                            78969
                                                 38798                  23
     3
                                 INSERT          78969                  3
                           UPDATE SET entity_id


2.                                    services
                    id         user_id server_id vds_id      entity_id
                  724786       78969                             3
                  338798                          2786          26
                  978969                 6783                  365

          UPDATE SET entity_id
Обертка в ORM
                                  EntHash                           Schema::Result::User

                                                     is_proxied()
                              EntHash::Proxy                        Schema::Result::Entity

                                                     client_id
                           EntHash::ProxyAux                        Schema::Result::Lbill

               tiehash
         Ent                  EntHash::User
                           is_proxied()
   Ent::User
hash_class()                                                     Schema::ResultSet::User
                    { prefetch => { entity =>'lbill' } }
list()                                                           search()
                 client_id                 lbill.client_id
                 is_proxied($_)            entity.$_
Неспешная миграция
1.   users.$fields
     servers.$fields      entity.$field
     vz_vds.$field
     services.user_id
     services.server_id   services.entity_id
     services.vds_id

2.   Ent::XXX­>new()      Schema­>resultset('XXX')­>new()

3.   SELECT * FROM xxx    Schema­>resultset('XXX')­>search()
Завершение рефакторинга
●   Удаление переехавших в entities полей из
    таблиц users, servers, vz_vds; полей user_id,
    server_id, vz_vds_id из таблицы services
●   Удаление миграционных триггеров
●   Удаление оберточных классов и прочих
    миграционных подпорок
Timeline рефакторинга
                   Создание таблиц
Написание триггеров Заполнение данными    Обертка ORM     1 релиз
 Замена plain SQL
   модификаций
                     users.$field →    Замена plain SQL
                     entities.$field      запросов
                                                          N релизов


         Удаление ненужных полей и подпорок               1 релиз
t
Вопросы?

More Related Content

What's hot

C++ STL & Qt. Занятие 03.
C++ STL & Qt. Занятие 03.C++ STL & Qt. Занятие 03.
C++ STL & Qt. Занятие 03.
Igor Shkulipa
 
C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.
Igor Shkulipa
 
C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.
Igor Shkulipa
 
C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.
Igor Shkulipa
 
Java Core. Lecture# 5. Concurrency.
Java Core. Lecture# 5. Concurrency.Java Core. Lecture# 5. Concurrency.
Java Core. Lecture# 5. Concurrency.
Anton Moiseenko
 
Java осень 2014 занятие 6
Java осень 2014 занятие 6Java осень 2014 занятие 6
Java осень 2014 занятие 6
Technopark
 
C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.
Igor Shkulipa
 
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
Badoo Development
 
C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.
Igor Shkulipa
 
Java осень 2014 занятие 7
Java осень 2014 занятие 7Java осень 2014 занятие 7
Java осень 2014 занятие 7
Technopark
 
Введение в сетевые технологии
Введение в сетевые технологииВведение в сетевые технологии
Введение в сетевые технологии
Unguryan Vitaliy
 
Сетевое взаимодействие
Сетевое взаимодействиеСетевое взаимодействие
Сетевое взаимодействие
Unguryan Vitaliy
 
10. java lecture generics&collections
10. java lecture generics&collections10. java lecture generics&collections
10. java lecture generics&collectionsMERA_school
 
Java Core. Lecture# 3. Part# 3. Multithreading.
Java Core. Lecture# 3. Part# 3. Multithreading.Java Core. Lecture# 3. Part# 3. Multithreading.
Java Core. Lecture# 3. Part# 3. Multithreading.
Anton Moiseenko
 
Java осень 2014 занятие 8
Java осень 2014 занятие 8Java осень 2014 занятие 8
Java осень 2014 занятие 8
Technopark
 
8. java lecture threads
8. java lecture threads8. java lecture threads
8. java lecture threadsMERA_school
 
работа с потоками ввода вывода
работа с потоками ввода выводаработа с потоками ввода вывода
работа с потоками ввода выводаmetaform
 
Архитектура. Доступноять программных систем.
Архитектура. Доступноять программных систем.Архитектура. Доступноять программных систем.
Архитектура. Доступноять программных систем.
Dima Dzuba
 

What's hot (18)

C++ STL & Qt. Занятие 03.
C++ STL & Qt. Занятие 03.C++ STL & Qt. Занятие 03.
C++ STL & Qt. Занятие 03.
 
C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.
 
C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.
 
C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.
 
Java Core. Lecture# 5. Concurrency.
Java Core. Lecture# 5. Concurrency.Java Core. Lecture# 5. Concurrency.
Java Core. Lecture# 5. Concurrency.
 
Java осень 2014 занятие 6
Java осень 2014 занятие 6Java осень 2014 занятие 6
Java осень 2014 занятие 6
 
C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.
 
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
 
C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.
 
Java осень 2014 занятие 7
Java осень 2014 занятие 7Java осень 2014 занятие 7
Java осень 2014 занятие 7
 
Введение в сетевые технологии
Введение в сетевые технологииВведение в сетевые технологии
Введение в сетевые технологии
 
Сетевое взаимодействие
Сетевое взаимодействиеСетевое взаимодействие
Сетевое взаимодействие
 
10. java lecture generics&collections
10. java lecture generics&collections10. java lecture generics&collections
10. java lecture generics&collections
 
Java Core. Lecture# 3. Part# 3. Multithreading.
Java Core. Lecture# 3. Part# 3. Multithreading.Java Core. Lecture# 3. Part# 3. Multithreading.
Java Core. Lecture# 3. Part# 3. Multithreading.
 
Java осень 2014 занятие 8
Java осень 2014 занятие 8Java осень 2014 занятие 8
Java осень 2014 занятие 8
 
8. java lecture threads
8. java lecture threads8. java lecture threads
8. java lecture threads
 
работа с потоками ввода вывода
работа с потоками ввода выводаработа с потоками ввода вывода
работа с потоками ввода вывода
 
Архитектура. Доступноять программных систем.
Архитектура. Доступноять программных систем.Архитектура. Доступноять программных систем.
Архитектура. Доступноять программных систем.
 

Viewers also liked

Alexandre.iline rit 2010 java_fxui_extra
Alexandre.iline rit 2010 java_fxui_extraAlexandre.iline rit 2010 java_fxui_extra
Alexandre.iline rit 2010 java_fxui_extra
rit2010
 
Sphinx new
Sphinx newSphinx new
Sphinx new
rit2010
 
Alexei shilov 2010 rit-rakudo
Alexei shilov 2010 rit-rakudoAlexei shilov 2010 rit-rakudo
Alexei shilov 2010 rit-rakudo
rit2010
 
Anatol filin pragmatic documentation 1_r
Anatol filin  pragmatic documentation 1_rAnatol filin  pragmatic documentation 1_r
Anatol filin pragmatic documentation 1_rrit2010
 
Microsoft cluster systems ritconf
Microsoft cluster systems ritconfMicrosoft cluster systems ritconf
Microsoft cluster systems ritconfrit2010
 
Партицирование и миграции данных на примере PostgreSQL, Денис Иванов (2ГИС)
Партицирование и миграции данных на примере PostgreSQL, Денис Иванов (2ГИС)Партицирование и миграции данных на примере PostgreSQL, Денис Иванов (2ГИС)
Партицирование и миграции данных на примере PostgreSQL, Денис Иванов (2ГИС)
Ontico
 
анатомия интернет банка Publish
анатомия интернет банка Publishанатомия интернет банка Publish
анатомия интернет банка Publishrit2010
 
анатомия интернет банка Publish
анатомия интернет банка Publishанатомия интернет банка Publish
анатомия интернет банка Publishrit2010
 
Ilia kantor паттерны серверных comet решений
Ilia kantor паттерны серверных comet решенийIlia kantor паттерны серверных comet решений
Ilia kantor паттерны серверных comet решенийrit2010
 

Viewers also liked (9)

Alexandre.iline rit 2010 java_fxui_extra
Alexandre.iline rit 2010 java_fxui_extraAlexandre.iline rit 2010 java_fxui_extra
Alexandre.iline rit 2010 java_fxui_extra
 
Sphinx new
Sphinx newSphinx new
Sphinx new
 
Alexei shilov 2010 rit-rakudo
Alexei shilov 2010 rit-rakudoAlexei shilov 2010 rit-rakudo
Alexei shilov 2010 rit-rakudo
 
Anatol filin pragmatic documentation 1_r
Anatol filin  pragmatic documentation 1_rAnatol filin  pragmatic documentation 1_r
Anatol filin pragmatic documentation 1_r
 
Microsoft cluster systems ritconf
Microsoft cluster systems ritconfMicrosoft cluster systems ritconf
Microsoft cluster systems ritconf
 
Партицирование и миграции данных на примере PostgreSQL, Денис Иванов (2ГИС)
Партицирование и миграции данных на примере PostgreSQL, Денис Иванов (2ГИС)Партицирование и миграции данных на примере PostgreSQL, Денис Иванов (2ГИС)
Партицирование и миграции данных на примере PostgreSQL, Денис Иванов (2ГИС)
 
анатомия интернет банка Publish
анатомия интернет банка Publishанатомия интернет банка Publish
анатомия интернет банка Publish
 
анатомия интернет банка Publish
анатомия интернет банка Publishанатомия интернет банка Publish
анатомия интернет банка Publish
 
Ilia kantor паттерны серверных comet решений
Ilia kantor паттерны серверных comet решенийIlia kantor паттерны серверных comet решений
Ilia kantor паттерны серверных comet решений
 

Similar to Aleksey Mashanov Rit

Лекция Android. БД SQLite, ContentProvider, Loader
Лекция Android. БД SQLite, ContentProvider, LoaderЛекция Android. БД SQLite, ContentProvider, Loader
Лекция Android. БД SQLite, ContentProvider, Loader
Александр Брич
 
Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularization
Ivan Krylov
 
Синхронный MODX: как сделать настоящую синхронизацию и не застрелиться
Синхронный MODX: как сделать настоящую синхронизацию и не застрелитьсяСинхронный MODX: как сделать настоящую синхронизацию и не застрелиться
Синхронный MODX: как сделать настоящую синхронизацию и не застрелиться
MODX Беларусь
 
ObjectManager, или как работать с большим количеством объектов на карте, Мари...
ObjectManager, или как работать с большим количеством объектов на карте, Мари...ObjectManager, или как работать с большим количеством объектов на карте, Мари...
ObjectManager, или как работать с большим количеством объектов на карте, Мари...
Ontico
 
Как это будет: ASP.NET Core
Как это будет: ASP.NET CoreКак это будет: ASP.NET Core
Как это будет: ASP.NET Core
DotNetConf
 
о некоторых вопросах бинарной совместимости в C++
о некоторых вопросах бинарной совместимости в C++о некоторых вопросах бинарной совместимости в C++
о некоторых вопросах бинарной совместимости в C++
corehard_by
 
Mastering Declarative Database Schema - MageConf 2019
Mastering Declarative Database Schema - MageConf 2019Mastering Declarative Database Schema - MageConf 2019
Mastering Declarative Database Schema - MageConf 2019
Max Pronko
 
Сергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
Сергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглитьСергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
Сергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
Tanya Denisyuk
 
C++ весна 2014 лекция 2
C++ весна 2014 лекция 2C++ весна 2014 лекция 2
C++ весна 2014 лекция 2Technopark
 
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
То, что вы хотели знать о HandlerSocket, но не смогли нагуглитьТо, что вы хотели знать о HandlerSocket, но не смогли нагуглить
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
php-user-group-minsk
 
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...Ontico
 
Cassandra db
Cassandra dbCassandra db
Cassandra db
Andrei Poliakov
 
6 создание распределенных приложений по технологии remoting
6 создание распределенных приложений по технологии remoting6 создание распределенных приложений по технологии remoting
6 создание распределенных приложений по технологии remoting
KewpaN
 
CodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQL
CodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQLCodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQL
CodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQLCodeFest
 
Народные средства оптимизации PostgreSQL
Народные средства оптимизации PostgreSQLНародные средства оптимизации PostgreSQL
Народные средства оптимизации PostgreSQL
Nikolay Pisarev
 
SQL-ник DevDay. Рубцов. Новое в Percona Server и MariaDB в сравнении с MySQL 5.5
SQL-ник DevDay. Рубцов. Новое в Percona Server и MariaDB в сравнении с MySQL 5.5SQL-ник DevDay. Рубцов. Новое в Percona Server и MariaDB в сравнении с MySQL 5.5
SQL-ник DevDay. Рубцов. Новое в Percona Server и MariaDB в сравнении с MySQL 5.5
DevDay
 
Расширение библиотеки Slick
Расширение библиотеки SlickРасширение библиотеки Slick
Расширение библиотеки Slick
Арсений Жижелев
 
django-and-postgresql
django-and-postgresqldjango-and-postgresql
django-and-postgresqlOleg Churkin
 
DEV Labs 2013. Can C++ Code Effeciency Be Comparable to That of Middle-Level ...
DEV Labs 2013. Can C++ Code Effeciency Be Comparable to That of Middle-Level ...DEV Labs 2013. Can C++ Code Effeciency Be Comparable to That of Middle-Level ...
DEV Labs 2013. Can C++ Code Effeciency Be Comparable to That of Middle-Level ...
Alex V. Petrov
 
АРК-ПЗ-1.pptx
АРК-ПЗ-1.pptxАРК-ПЗ-1.pptx
АРК-ПЗ-1.pptx
robete3065
 

Similar to Aleksey Mashanov Rit (20)

Лекция Android. БД SQLite, ContentProvider, Loader
Лекция Android. БД SQLite, ContentProvider, LoaderЛекция Android. БД SQLite, ContentProvider, Loader
Лекция Android. БД SQLite, ContentProvider, Loader
 
Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularization
 
Синхронный MODX: как сделать настоящую синхронизацию и не застрелиться
Синхронный MODX: как сделать настоящую синхронизацию и не застрелитьсяСинхронный MODX: как сделать настоящую синхронизацию и не застрелиться
Синхронный MODX: как сделать настоящую синхронизацию и не застрелиться
 
ObjectManager, или как работать с большим количеством объектов на карте, Мари...
ObjectManager, или как работать с большим количеством объектов на карте, Мари...ObjectManager, или как работать с большим количеством объектов на карте, Мари...
ObjectManager, или как работать с большим количеством объектов на карте, Мари...
 
Как это будет: ASP.NET Core
Как это будет: ASP.NET CoreКак это будет: ASP.NET Core
Как это будет: ASP.NET Core
 
о некоторых вопросах бинарной совместимости в C++
о некоторых вопросах бинарной совместимости в C++о некоторых вопросах бинарной совместимости в C++
о некоторых вопросах бинарной совместимости в C++
 
Mastering Declarative Database Schema - MageConf 2019
Mastering Declarative Database Schema - MageConf 2019Mastering Declarative Database Schema - MageConf 2019
Mastering Declarative Database Schema - MageConf 2019
 
Сергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
Сергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглитьСергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
Сергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
 
C++ весна 2014 лекция 2
C++ весна 2014 лекция 2C++ весна 2014 лекция 2
C++ весна 2014 лекция 2
 
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
То, что вы хотели знать о HandlerSocket, но не смогли нагуглитьТо, что вы хотели знать о HandlerSocket, но не смогли нагуглить
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
 
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...
 
Cassandra db
Cassandra dbCassandra db
Cassandra db
 
6 создание распределенных приложений по технологии remoting
6 создание распределенных приложений по технологии remoting6 создание распределенных приложений по технологии remoting
6 создание распределенных приложений по технологии remoting
 
CodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQL
CodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQLCodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQL
CodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQL
 
Народные средства оптимизации PostgreSQL
Народные средства оптимизации PostgreSQLНародные средства оптимизации PostgreSQL
Народные средства оптимизации PostgreSQL
 
SQL-ник DevDay. Рубцов. Новое в Percona Server и MariaDB в сравнении с MySQL 5.5
SQL-ник DevDay. Рубцов. Новое в Percona Server и MariaDB в сравнении с MySQL 5.5SQL-ник DevDay. Рубцов. Новое в Percona Server и MariaDB в сравнении с MySQL 5.5
SQL-ник DevDay. Рубцов. Новое в Percona Server и MariaDB в сравнении с MySQL 5.5
 
Расширение библиотеки Slick
Расширение библиотеки SlickРасширение библиотеки Slick
Расширение библиотеки Slick
 
django-and-postgresql
django-and-postgresqldjango-and-postgresql
django-and-postgresql
 
DEV Labs 2013. Can C++ Code Effeciency Be Comparable to That of Middle-Level ...
DEV Labs 2013. Can C++ Code Effeciency Be Comparable to That of Middle-Level ...DEV Labs 2013. Can C++ Code Effeciency Be Comparable to That of Middle-Level ...
DEV Labs 2013. Can C++ Code Effeciency Be Comparable to That of Middle-Level ...
 
АРК-ПЗ-1.pptx
АРК-ПЗ-1.pptxАРК-ПЗ-1.pptx
АРК-ПЗ-1.pptx
 

More from rit2010

Konstantin kolomeetz послание внутреннему заказчику
Konstantin kolomeetz послание внутреннему заказчикуKonstantin kolomeetz послание внутреннему заказчику
Konstantin kolomeetz послание внутреннему заказчикуrit2010
 
Bykov monitoring mailru
Bykov monitoring mailruBykov monitoring mailru
Bykov monitoring mailrurit2010
 
Alexander shigin slides
Alexander shigin slidesAlexander shigin slides
Alexander shigin slidesrit2010
 
иван василевич Eye tracking и нейрокомпьютерный интерфейс
иван василевич Eye tracking и нейрокомпьютерный интерфейсиван василевич Eye tracking и нейрокомпьютерный интерфейс
иван василевич Eye tracking и нейрокомпьютерный интерфейсrit2010
 
Andrey Petrov P D P
Andrey Petrov P D PAndrey Petrov P D P
Andrey Petrov P D Prit2010
 
Andrey Petrov методология P D P, часть 1, цели вместо кейсов
Andrey Petrov методология P D P, часть 1, цели вместо кейсовAndrey Petrov методология P D P, часть 1, цели вместо кейсов
Andrey Petrov методология P D P, часть 1, цели вместо кейсовrit2010
 
Dmitry lohansky rit2010
Dmitry lohansky rit2010Dmitry lohansky rit2010
Dmitry lohansky rit2010rit2010
 
Dmitry Lohansky Rit2010
Dmitry Lohansky Rit2010Dmitry Lohansky Rit2010
Dmitry Lohansky Rit2010rit2010
 
Related Queries Braslavski Yandex
Related Queries Braslavski YandexRelated Queries Braslavski Yandex
Related Queries Braslavski Yandexrit2010
 
молчанов сергей датацентры 10 04 2010 Light
молчанов сергей датацентры 10 04 2010  Lightмолчанов сергей датацентры 10 04 2010  Light
молчанов сергей датацентры 10 04 2010 Lightrit2010
 
Sergey Ilinsky Rit 2010 Complex Gui Development Ample Sdk
Sergey Ilinsky Rit 2010 Complex Gui Development Ample SdkSergey Ilinsky Rit 2010 Complex Gui Development Ample Sdk
Sergey Ilinsky Rit 2010 Complex Gui Development Ample Sdkrit2010
 
Serge P Nekoval Grails
Serge P  Nekoval GrailsSerge P  Nekoval Grails
Serge P Nekoval Grailsrit2010
 
Pavel Braslavski Related Queries Braslavski Yandex
Pavel Braslavski Related Queries Braslavski YandexPavel Braslavski Related Queries Braslavski Yandex
Pavel Braslavski Related Queries Braslavski Yandexrit2010
 
Max Lapshin Erlyvideo V2
Max Lapshin Erlyvideo V2Max Lapshin Erlyvideo V2
Max Lapshin Erlyvideo V2rit2010
 
Eugene Lisitsky Web Sockets
Eugene Lisitsky Web SocketsEugene Lisitsky Web Sockets
Eugene Lisitsky Web Socketsrit2010
 
Alexey Bazhin Balancing
Alexey Bazhin BalancingAlexey Bazhin Balancing
Alexey Bazhin Balancingrit2010
 
рит, нефункциональная структура команды, безуглый
рит, нефункциональная структура команды, безуглыйрит, нефункциональная структура команды, безуглый
рит, нефункциональная структура команды, безуглыйrit2010
 
левин михаил выступление на рит большие картинки
левин михаил выступление на рит   большие картинкилевин михаил выступление на рит   большие картинки
левин михаил выступление на рит большие картинкиrit2010
 
левин михаил выступление на рит
левин михаил выступление на ритлевин михаил выступление на рит
левин михаил выступление на ритrit2010
 
антон веснин Rails Application Servers
антон веснин Rails Application Serversантон веснин Rails Application Servers
антон веснин Rails Application Serversrit2010
 

More from rit2010 (20)

Konstantin kolomeetz послание внутреннему заказчику
Konstantin kolomeetz послание внутреннему заказчикуKonstantin kolomeetz послание внутреннему заказчику
Konstantin kolomeetz послание внутреннему заказчику
 
Bykov monitoring mailru
Bykov monitoring mailruBykov monitoring mailru
Bykov monitoring mailru
 
Alexander shigin slides
Alexander shigin slidesAlexander shigin slides
Alexander shigin slides
 
иван василевич Eye tracking и нейрокомпьютерный интерфейс
иван василевич Eye tracking и нейрокомпьютерный интерфейсиван василевич Eye tracking и нейрокомпьютерный интерфейс
иван василевич Eye tracking и нейрокомпьютерный интерфейс
 
Andrey Petrov P D P
Andrey Petrov P D PAndrey Petrov P D P
Andrey Petrov P D P
 
Andrey Petrov методология P D P, часть 1, цели вместо кейсов
Andrey Petrov методология P D P, часть 1, цели вместо кейсовAndrey Petrov методология P D P, часть 1, цели вместо кейсов
Andrey Petrov методология P D P, часть 1, цели вместо кейсов
 
Dmitry lohansky rit2010
Dmitry lohansky rit2010Dmitry lohansky rit2010
Dmitry lohansky rit2010
 
Dmitry Lohansky Rit2010
Dmitry Lohansky Rit2010Dmitry Lohansky Rit2010
Dmitry Lohansky Rit2010
 
Related Queries Braslavski Yandex
Related Queries Braslavski YandexRelated Queries Braslavski Yandex
Related Queries Braslavski Yandex
 
молчанов сергей датацентры 10 04 2010 Light
молчанов сергей датацентры 10 04 2010  Lightмолчанов сергей датацентры 10 04 2010  Light
молчанов сергей датацентры 10 04 2010 Light
 
Sergey Ilinsky Rit 2010 Complex Gui Development Ample Sdk
Sergey Ilinsky Rit 2010 Complex Gui Development Ample SdkSergey Ilinsky Rit 2010 Complex Gui Development Ample Sdk
Sergey Ilinsky Rit 2010 Complex Gui Development Ample Sdk
 
Serge P Nekoval Grails
Serge P  Nekoval GrailsSerge P  Nekoval Grails
Serge P Nekoval Grails
 
Pavel Braslavski Related Queries Braslavski Yandex
Pavel Braslavski Related Queries Braslavski YandexPavel Braslavski Related Queries Braslavski Yandex
Pavel Braslavski Related Queries Braslavski Yandex
 
Max Lapshin Erlyvideo V2
Max Lapshin Erlyvideo V2Max Lapshin Erlyvideo V2
Max Lapshin Erlyvideo V2
 
Eugene Lisitsky Web Sockets
Eugene Lisitsky Web SocketsEugene Lisitsky Web Sockets
Eugene Lisitsky Web Sockets
 
Alexey Bazhin Balancing
Alexey Bazhin BalancingAlexey Bazhin Balancing
Alexey Bazhin Balancing
 
рит, нефункциональная структура команды, безуглый
рит, нефункциональная структура команды, безуглыйрит, нефункциональная структура команды, безуглый
рит, нефункциональная структура команды, безуглый
 
левин михаил выступление на рит большие картинки
левин михаил выступление на рит   большие картинкилевин михаил выступление на рит   большие картинки
левин михаил выступление на рит большие картинки
 
левин михаил выступление на рит
левин михаил выступление на ритлевин михаил выступление на рит
левин михаил выступление на рит
 
антон веснин Rails Application Servers
антон веснин Rails Application Serversантон веснин Rails Application Servers
антон веснин Rails Application Servers
 

Aleksey Mashanov Rit

  • 2. Цели рефакторинга ● Упрощение добавления новых возможностей за счет возможности реиспользования кода. ● Упрощение сопровождения кода за счет приведения его в человекочитаемый вид, нормализации кода и структуры базы. ● Избавление от велосипедов и перенос тем самым головной боли по их развитию и поддержке на сообщество.
  • 3. Характеристики системы ● Perl + PostgreSQL ● ~ 1200 модулей и 400 скриптов ● ~ 300000 строк чистого кода ● ~ 450 таблиц в БД ● ~ 150 хранимых процедур и 140 триггеров
  • 4. Разбиение на этапы Этап рефакторинга —  коммит должен укладываться  в рамки одного релиза t Релиз (3­4 недели) Шаг рефакторинга —  изменение не сказывающееся  на работоспособности системы Рефакторинг выполняется в основной ветке разработки
  • 5. Test Driven Refactioring Для каждого вносимого в код изменения Написание автотеста Проверка автотеста путем поломки тестируемого кода Внесение модификации (рефакторинг) Проверка модифицированного кода автотестом
  • 6. Структура автотестов Test::Class My::Test rollback после  lib/ t/lib/ каждого теста Class1 Class1::Test Class2 Class2::Sub1 Class2::Test Class2::Sub1::Test Class3 Class2::Sub2 Class3::Test Class2::Sub2::Test
  • 8. Структура до рефакторинга Ent Ent::Smth11 Entity Entity::Smth11 new() new() Ent::Smth12 Entity::Smth12 list() list() get() … get() … set() set() save() Ent::Smth1N save() Entity::Smth1N ● Два примерно одинаковых ORM ● Методы модификации и поиска объединены в одном классе ● Доступ к полям объекта как к элементам хэша
  • 9. Что хотим получить DBIx::Class::Row Schema::Result::Smth11 DBIx::Class::ResultSet Schema::ResultSet::Smth11 new() Schema::Result::Smth12 search() Schema::ResultSet::Smth12 get_column() … … set_column() Schema::Result::Smth1N Schema::ResultSet::Smth1N insert() update() Schema::Result::Smth21 Schema::ResultSet::Smth21 Schema::Result::Smth22 Schema::ResultSet::Smth22 … … Schema::Result::Smth2N Schema::ResultSet::Smth2N ● Один ORM ● Методы модификации и поиска в разных классах ● Доступ к полям объекта через акцессоры
  • 10. Зачем? ● До рефакторинга ● Два самописных ORM в одной системе это слишком много ● Оба из них не поддерживают отношений между таблицами, тем не менее они нам необходимы, что приводит к обилию в коде plain SQL запросов ● Вновьприбывшие разработчики вынуждены с ними разбираться и вникать в их отличия ● После рефакторинга ● Много новых хороших возможностей, которым мы все очень рады ● Мы не одни во вселенной: почти все что нам может понадобиться уже изобрели, реализовали, отладили и устранили почти все баги, а какие не устранили, устраняют довольно-таки быстро ● Опыт работы с DBIx::Class разработчику пригодится не только для работы над нашей системой, поэтому он с большей вероятностью потрудится разобраться в нем поглубже
  • 11. Создание схемы table table table схема DBIx::Class::Schema::Loader code style conventions simple perl script выстраиваем нужную  иерархию Schema::Result::* Используем статическую схему DBIx::Class::Schema
  • 12. Схема обертки tiehash Ent EntHash Schema::Result::SmthX new() FETCH() get_coumn() set() STORE() set_column() get() EXISTS() has_column_loaded() list() NEXTKEY() columns() save() _DBIC_ insert_or_update() _DBICRS_ Ent::SmthN Ent::Smth2 Schema::ResultSet::SmthX dbic_class() Ent::Smth1 dbic_class() search() dbic_class()
  • 13. Callback методы DBIx::Class::Core Ent::* save() DBIC::EntCallback delete() insert() update() delete() да нет Schema::Result::* caller() eq 'Ent'
  • 14. Неспешная миграция 1. Ent::XXX­>... Schema­>resultset('XXX')­>... 2. SELECT * FROM xxx Schema­>resultset('XXX')­>select() 3. Ent::XXX­>save() Schema::Result::XXX­>insert() Schema::Result::XXX­>update() Ent::XXX­>delete() Schema::Result::XXX­>delete()
  • 15. Завершение рефакторинга ● Удаление иерархии старых ORM
  • 16. Timeline рефакторинга Схема таблиц Schema::* Обертка Ent вокруг DBIx::Class 1 релиз Callback методов Перенос хуков в Избавление Замена Ent::* → Schema::Result::* от plain SQL N релизов Schema­>resultset('*') Удаление старого ORM 1 релиз t
  • 18. Исходная структура Service связан с объектом одного из трех Lbill Client ● классов, а не с одним. ● User, Server, VDS имеют примерно одинаковый набор финансовых полей, но не используют наследование. ● Лишняя связь от User, Server, VDS к Client. User Server VDS ● Сложные запросы к базе со множественными LEFT JOIN. ● Добавление новой сущности приводит к созданию 1 класса, 3 связей и модификации Service. Service
  • 19. Желаемая структура ● Добавление новой сущности Client приводит к добавлению 1 класса и 1 связи. Lbill User ● Финансовые операции ограничены работой с Entity, а не с тремя User, Server, VDS. Entity Server ● При добавлении новой сущности большинство возможностей (кроме Service VDS технических) - «из коробки». ● Нет лишних связей (нормализация).
  • 20. Структура базы vz_vds vz_vds servers clients servers id id users id users id identity_id client_id id id entity_id client_id lbills технические  lbill_id entity_id client_id технические  lbill_id id поля lbill_id финансовые  технические  поля финансовые  client_id поля поля финансовые  поля технические  поля services services entities технические  поля технические  поля user_id entity_id id поля server_id lbill_id vz_vds_id финансовые  поля Было Стало
  • 21. Миграционные триггеры entities AFTER UPDATE Обновление соответствующих финансовых полей в  таблицах users, servers, vz_vds при их изменении BEFORE INSERT vz_vds 1.Проверка, что все синхронизируемые из entities поля IS  servers NULL — это означает, что не выполняется попытка  users установить их значение при INSERT 2.Автоматическое заполнение синхронизируемых полей  данными из соответствующей записи в entities AFTER INSERT OR UPDATE Проверка, что все значения полей соответствуют  значениям всех соответствующих полей в таблице entities
  • 22. Заполнение данными vz_vds id servers entity_id entities 24786 id 1 users entity_id 38798 2 1. id 24786 id 78969 38798 1 entity_id 3 1 24786 12 2 78969 38798 23 3 INSERT 78969 3 UPDATE SET entity_id 2. services id user_id server_id vds_id entity_id 724786 78969 3 338798 2786 26 978969 6783 365 UPDATE SET entity_id
  • 23. Обертка в ORM EntHash Schema::Result::User is_proxied() EntHash::Proxy Schema::Result::Entity client_id EntHash::ProxyAux Schema::Result::Lbill tiehash Ent EntHash::User is_proxied() Ent::User hash_class() Schema::ResultSet::User { prefetch => { entity =>'lbill' } } list() search() client_id lbill.client_id is_proxied($_) entity.$_
  • 24. Неспешная миграция 1. users.$fields servers.$fields entity.$field vz_vds.$field services.user_id services.server_id services.entity_id services.vds_id 2. Ent::XXX­>new() Schema­>resultset('XXX')­>new() 3. SELECT * FROM xxx Schema­>resultset('XXX')­>search()
  • 25. Завершение рефакторинга ● Удаление переехавших в entities полей из таблиц users, servers, vz_vds; полей user_id, server_id, vz_vds_id из таблицы services ● Удаление миграционных триггеров ● Удаление оберточных классов и прочих миграционных подпорок
  • 26. Timeline рефакторинга Создание таблиц Написание триггеров Заполнение данными Обертка ORM 1 релиз Замена plain SQL модификаций users.$field → Замена plain SQL entities.$field запросов N релизов Удаление ненужных полей и подпорок 1 релиз t