Valery's Mlog

Mindlog of a Freak
May 19th, 2005 by Valery Dachev

Персистенция

Дойдоха ми в главата няколко идеи за преправяне на проекта ми. Основното си остава персистенцията (един вид съхраняването) на класовете данни (в моя случай) в релационна база данни. В Java за целта съществува “Hibernate” – проект, за който Лъчезар Добрев бе??е изкарал много добра лекция по време на един семинар на БАРС (на практическата част, уви, не можах да присъствам). Хората са се втурнали неслучайно да пи??ат подобно нещо и за .NET Framework. Подобни наченки има за PHP, но все нещо им куца (може би ще се хвана да направя преглед на няколко от тези проекти). Трудността в написването на ne]o такова за PHP се състои в слабата обектна ориентираност на версиите на PHP преди PHP5 – калпаво онаследяване на обектите, липсват статични методи и обекти, както и контрол над достъпа до тях, няма изключения (Всъщност за нововъведенията в PHP5 бях писал някъде из блога си преди време). Ползата от този подход, освен в спестяването на значително количество код, е в няколко други важни насоки: унифицира се работата с различните обекти, а прехода към друга база (или боза) данни (например от MySQL към PostgreSQL в моя случай) става с промяната само на класа за персистенция.

Блъскам си главата аз в написването на собствен клас за персистенция на данни (не че ще направя нещо кой-знае колко значимо де :D) и ми се ще??е да заблъскам и нечия друга глава в това, че да не си товаря само аз мозъка (макар че други къде-къде по-компетентни от мен със сигурност са си бъркали сивото вещество с тия неща :)). Това, което си направих аз: обект Persistent, който оперира с базата данни чрез методи като insert(), update(), delete() и select(). Всички обекти онаследяват Persistent. Всяка инстанция на такъв обект съответства на ред от таблицата, описанието на която конструкторът на обекта подава като параметър на конструктора на Persistent (доколкото това става експлицитно поне в PHP4. ToDo: да се направи съвместимо с PHP5). Този простичък механизъм покрива до голяма степен нуждите за работа със самостоятелни обекти (в моя случай засега на 5 от общи 19те класа, с които работя). Да се покрие обаче по-голяма от “простичката” функционалност не е тривиална и изисква солидна доработка. Къде са проблемите:

  • Всяка инстанция на обекта всъщност е ред от съответната таблица. Какво става обаче, когато трябва да обновя няколко реда отговарящи на някакво условие ? Нормално, пи??е се един статичен (или в случая с PHP4 – просто) обект, който да го прави. Обаче имаме инстанции на този клас, които съдържат данни. Те трябва да бъдат подменени, а няма как да се знаят всички инстанции от този клас. В този случай (както и при повечето, когато ни липсват статични методи и полета) може да се направи глобален масив (който може да изпълнява ролята на ке??), където да се съхраняват данните от базата, а полетата в класовете да бъдат references към тези данни. Така метода просто трябва да извър??и същата операция върху данните от “ке??а”. Получава се обаче изли??но натоварване. Още повече, че няма гаранция дали нещо друго няма да пипа по таблиците и това да направи данните в ке??а несъответстващи на тези в базата. Отчасти причина за този проблем е липсата на някакъв application server и механизъм, чрез който trigger да задейства изчистването на ке??а в него. Тук ре??ението ми се замъглява.
  • Една много важна думичка в термина “релационна база данни” е думичката “релационна”. Нека искам да взема всички продукти в дадена категория. Доколкото продуктите могат да бъдат в няколко категории едновременно, тези релации се описват от отделна таблица, а заявката, която трябва да сглобя, трябва да минава през съответната таблица. В този случай ре??ение още не съм си намерил. “Простичкият механизъм” не вър??и работа, тъй като трябва да има не просто описание на таблицата, ами и релациите с други таблии и начина, по който става това. Начинът, по който ще се зададе условието пък ми е още по-любопитен (ToDo: да видя как са го направили умните хора с Hibernate). От доста време се каня да разчовъркам LDAP. Може би ще се окаже по-елегантен метод за персистенция.
  • Аз лично имам навика да съхранявам картинки по базите данни. Това значително олеснява преместването на системата от една на друга ма??ина. Какво обаче става при персистенцията: създавам инстанция на някакъв клас “image” с определен ключ (стойността на първичния ключ в таблицата). В този момент целия ред от таблицата се издърпва, което включва и самата картинка ! ??зли??но хабене на памет, ако тя може въобще да не ми е нужна (например искам да сравня големината на картинката в ке??а на файловата система, с този в базата данни). Това изисква специално третиране на такива полета и, ако това специално третиране не стане в класа за персистенция, погазва всякаква унификация за работа с данните от класа.
  • Друг проблем е самия брой на заявките към SQL сървъра. От една страна, повече заявки гарантират съответствие на данните в него и тези в PHP скрипта. От друга обаче, повече заявки означават по-голямо натоварване. Този проблем пък е пряко свързан с това доколко са атомични операциите, които се извър??ват от обектите, за да може вътре в самия клас за персистенция да се включи използването на транзакции или заключване на таблиците, като по-голяма гаранция, че данните SQLа не са подменени от друг процес.

Мисля все пак, когато довър??а въпросния клас за MySQL и направя още един за PostgreSQL, да ги публикувам под BSD лиценз. Току-виж свър??или некому работа…

P.S. Не знам дали е заради тези неща, но пак ми расте мъдрец. Блаф !

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: