[PHP, SQL] Как я решил написать ORM на php с нуля на работающем сайте, и что из этого вышло
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Я, как и многие программисты, довольно отрицательно отношусь к созданию велосипедов и изобретению колес и это более чем обосновано хотя бы стоимостью разработки для бизнеса. Но как показал мой опыт иногда приходится отходить от этого правила и, даже, получать от этого пользу. Я имею ввиду не только интерес и удовольствие от разработки, но и плюшки для проекта в целом. Об одном моем подобном опыте можно прочесть несколько слов под катом.
Введение
То как сейчас мы создаем веб-приложения сильно отличается от кода, пришедшего к нам на поддержку из стародавних времен, когда по телевизору показывали Фабрику Звезд, модно было ходить с расклодушкой, а PHP только начинал приобретать признаки Объектно-ориентированного языка. Программирование в нулевые мне представляется великолепной иллюстрацией к идеям Дарвина: тогда почти любой разработчик-одиночка создавал собственные решения, некоторые из них захватывали умы более чем одного человека, и пройдя ускоренный естественный отбор, фреймворки и CMS стали титульными, образцами лучших и наиболее популярных методов разработки. В некоторых случаях, все же, только популярными, без слова «хорошее» или тем паче «лучшее».
Но в отличии от динозавров и мамонтов далеко не все альтернативные решения ушли в небытие, особенно на бекэнд, и я знаю об этом не понаслышке. Мне довелось поработать, не скажу с большим, но довольно солидным количеством legacy на php. Кое-что было просто ужасно, а некоторые сайты и даже CMS были довольно интересные. Мне нравится иногда покопаться в том, что рождалось в умах первопроходцев. Тогда не было такой стандартизации, и хотя чаще всего это превосходный материал для изучения анти-паттернов, но этот код меня забавляет, делает работу похожей на ИТ-археологию.
Возлюбленное наследие
Лично мне нравится в работе с работающими сайтами на legacy — внести правку, убрать какой-то дикий костыль, уменьшить уровень хаоса и при этом не сломать работу всей системы. Чувствую в такие моменты себя человеком, сделавшим этот мир немного лучше, и это круто.
print " <button onClick='domultimove();' class=controlbutton><img src=syspix/ico32_move.gif border=0><br>перенос</button>";
print "<b>" . $ITEM->Description . "</b>:<br>";
$browsebgcolor = "#D9D9D9";
$sql = "select i.ID, m.Name, i.perm, i.descr from item4 i inner join main m on i.ID=m.ElementID";
echo "<script language='JavaScript'> document.location='" . $_SERVER['PHP_SELF']";
Частой отличительной чертой legacy является каша из кода, написанного на разных языках, хотя и в современной разработке, конечно же, мы в PHP классы можем добавлять, например, код на SQL. Но я говорю о другом, в legacy нередко идет поток вселенской мысли разработчика — о чем и на какой языке он думал, то и писал потоком. Я хочу рассказать о подобной ситуации с одним мега-олдскульным CMS-решением, с которым работал некоторое время. Там все было настолько «чудесно», что я просто очень рад, что смог все-таки кое-что исправить и сделать так, чтобы сайт стал работать существенно корректней и быстрее.
Итак, мне в работу попал сайт крупной компании, написанный в первой половине двухтысячных. В этом проекте все базировалось на классах с одним методом, в котором происходило все: и работа с логикой, и вывод интерфейса (view) и обращения к базе, при чем, sql был прям там же между командами
print "<table>";
. Вносить правки в работающий на таком коде сайт, кстати, с неплохой посещаемостью и коммерческой составляющей, представляло из себя не самое приятное, но очень веселое мероприятие.
Нетрудно догадаться, что я сильно облегчил жизнь бекэнд-разработчиков, для начала вынеся вывод верстки в шаблоны. Для этого я использовал уже готовый и довольно популярный шаблонизатор twig. Это было несложно и быстро, так что я даже не особо и выделял время на рефакторинг. Следующим шагом по-моему мнению нужно было что-то сделать с запросами к базе данных, в конце концов, MVC не зря так популярна у нас в веб.
Насмотревшись на Симфони и Ларавел, я решил, что и здесь подход с использованием ORM отлично впишется. Поможет вынести работу с Базой Данных и оставить пока еще не-до-контроллерам только работу уже с полученными данными. Логично и совершенно правильно использовать уже существующие решения. Поэтому перво-наперво я ринулся в packagist посмотреть, какие альтернативы у меня есть кроме Docktrine, но хорошенько подумав, пришел к неутешительному выводу, что это не столь важно. Дело в том, что в этом проекте была довольно необычная структура данных. Такого я не встречал нигде более, хотя я работал с MODx :) Передо мной встала проблема: использовать популярные open-source ORM так, как я хочу не получится, ну, по крайней мере это будет то еще приключение. Так я решился на создание велосипеда.
Немного про то, что же я сделал
Да, я решил, что напишу ORM на PHP с нуля (нет, ну идеи и концепции перенятые у того же Docktrine у меня-то были) специально для этого проекта, да так, чтобы это работало со структурой данных. Ведь это рабочий сайт, и никто не был готов выделять ресурсы программистов на задачи «переписать все с нуля с нормальной структурой БД». Праотцы основавшие эту CMS создали 2 типа объектов, при чем один из них еще и делился на внутренние «типы данных»: ресурсы, у которых есть даты, ссылки, разные типы текста, изображения и еще ряд хранились в 2 таблицах, но были и объекты, хранящиеся в одной таблице, их думаю можно назвать системными данными.
Я не хотел, чтобы применяя обращения к моделям, приходилось бы думать о джоинах, или хотя бы постараться сократить такие моменты до минимума. Поэтому я решил, что модели должны быть двух типов: для одно-табличных объектов и для основных двух-табличных. Так как у этих Моделей-классов много общих методов, тот же ORDER BY или LIMIT, поэтому каждый базовый класс, на основании которого и будут создаваться конкретные Модели, я наследовал от общего Абстрактного класса.
Как можно видеть из дерева, я так же добавил поддержку разных типов Баз Данных, что в данном случае избыточно. Но я в тот момент вошел в «поток» и творил :). Также очень правильным в данном случае шагом явилось, то что я делал это на базе PDO, ибо использовавшийся в коде php-mysql не позволял переводить сайт на седьмую версию языка, а это хотелось исправить на корню, как говориться.
$element = (new Model())->getOne($id);
Благодаря тому, что я хорошенько разобрался в логике структуры Базы данных, у меня получилось сделать поиск и получение ресурса только по его ID, даже не зная каким внутренним типом данных обладает ресурс, что было обязательно при старом подходе. Настоящая объектная работа с данными, и мы забываем об sql в коде.
Заключительные абзацы...
Эта работа принесла 2 неожиданных для меня поворота. Во-первых, я попытался все написать сразу в виде кода, и ничего не получилось. Мне пришлось взять ручку, блокнот, выйти на природу и под щебет воробьев и жужжание пчел сначала нарисовать, что я хочу получить, как это будет связано, какие мне нужны классы, и как это будет вызываться в коде «контроллеров». Кстати, потом реализация отличалась от изначальных зарисовок совсем незначительно. Так что, если программист ничего не кодит, это еще не значит, что он ничего полезного не делает.
Во-вторых, я справился очень быстро, многие бизнесы не любят, когда программисты тратят время на всякие не понятные рефакторинги. Я реализовал весь проект в течении примерно недели, параллельно занимаясь поставленными задачами по внедрению новых features.
Теми плюсами, о которых я заявлял в начале статьи я отмечу: последовательность и постепенность замены уже существующего кода на работающем проекте, а значит и отсутствие необходимости выделять больше времени на переход, рефакторинг кода в рамках поступающих задач. На этом откланяюсь, благодарю за чтение.
===========
Источник:
habr.com
===========
Похожие новости:
- [Разработка под iOS, Разработка мобильных приложений, Разработка под Android] «Студийные» приложения Netflix на Android и iOS теперь с Kotlin Multiplatform (перевод)
- [Высокая производительность, Разработка веб-сайтов, JavaScript, Клиентская оптимизация, ReactJS] Производительность приложений, работающих с Video и Audio
- [Разработка веб-сайтов, PHP, Laravel] Laravel–Дайджест (2–8 ноября 2020)
- [Поисковые технологии, PHP, MySQL, JavaScript, Функциональное программирование] Pick — самая маленькая поисковая система на PHP и MySQL
- [Java, NoSQL, Big Data, Машинное обучение, Natural Language Processing] Кластеризация и классификация больших Текстовых данных с помощью машинного обучения на Java. Статья #1 — Теория
- [Java, NoSQL, Apache] Как быстро загрузить большую таблицу в Apache Ignite через Key-Value API
- [PostgreSQL, SQL] PostgreSQL отложенные SQL ограничения (перевод)
- [Криптография, Python, SQLite, GitHub, Криптовалюты] Внедряем оплату BTC куда угодно (Python)
- [Open source, Администрирование баз данных, Хранение данных] openGauss: новая СУБД от Huawei для нагруженных enterprise-проектов прибавила в функциональности
- [Разработка мобильных приложений] Как Kotlin Multiplatform экономит время на разработку. Личный опыт создания игрового приложения для KotlinConf 2019
Теги для поиска: #_php, #_sql, #_reljatsionnye_bazy_dannyh (реляционные базы данных), #_legacy_code, #_php, #_orm, #_php, #_sql
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 22:29
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Я, как и многие программисты, довольно отрицательно отношусь к созданию велосипедов и изобретению колес и это более чем обосновано хотя бы стоимостью разработки для бизнеса. Но как показал мой опыт иногда приходится отходить от этого правила и, даже, получать от этого пользу. Я имею ввиду не только интерес и удовольствие от разработки, но и плюшки для проекта в целом. Об одном моем подобном опыте можно прочесть несколько слов под катом. Введение То как сейчас мы создаем веб-приложения сильно отличается от кода, пришедшего к нам на поддержку из стародавних времен, когда по телевизору показывали Фабрику Звезд, модно было ходить с расклодушкой, а PHP только начинал приобретать признаки Объектно-ориентированного языка. Программирование в нулевые мне представляется великолепной иллюстрацией к идеям Дарвина: тогда почти любой разработчик-одиночка создавал собственные решения, некоторые из них захватывали умы более чем одного человека, и пройдя ускоренный естественный отбор, фреймворки и CMS стали титульными, образцами лучших и наиболее популярных методов разработки. В некоторых случаях, все же, только популярными, без слова «хорошее» или тем паче «лучшее». Но в отличии от динозавров и мамонтов далеко не все альтернативные решения ушли в небытие, особенно на бекэнд, и я знаю об этом не понаслышке. Мне довелось поработать, не скажу с большим, но довольно солидным количеством legacy на php. Кое-что было просто ужасно, а некоторые сайты и даже CMS были довольно интересные. Мне нравится иногда покопаться в том, что рождалось в умах первопроходцев. Тогда не было такой стандартизации, и хотя чаще всего это превосходный материал для изучения анти-паттернов, но этот код меня забавляет, делает работу похожей на ИТ-археологию. Возлюбленное наследие Лично мне нравится в работе с работающими сайтами на legacy — внести правку, убрать какой-то дикий костыль, уменьшить уровень хаоса и при этом не сломать работу всей системы. Чувствую в такие моменты себя человеком, сделавшим этот мир немного лучше, и это круто. print " <button onClick='domultimove();' class=controlbutton><img src=syspix/ico32_move.gif border=0><br>перенос</button>";
print "<b>" . $ITEM->Description . "</b>:<br>"; $browsebgcolor = "#D9D9D9"; $sql = "select i.ID, m.Name, i.perm, i.descr from item4 i inner join main m on i.ID=m.ElementID"; echo "<script language='JavaScript'> document.location='" . $_SERVER['PHP_SELF']"; Частой отличительной чертой legacy является каша из кода, написанного на разных языках, хотя и в современной разработке, конечно же, мы в PHP классы можем добавлять, например, код на SQL. Но я говорю о другом, в legacy нередко идет поток вселенской мысли разработчика — о чем и на какой языке он думал, то и писал потоком. Я хочу рассказать о подобной ситуации с одним мега-олдскульным CMS-решением, с которым работал некоторое время. Там все было настолько «чудесно», что я просто очень рад, что смог все-таки кое-что исправить и сделать так, чтобы сайт стал работать существенно корректней и быстрее. Итак, мне в работу попал сайт крупной компании, написанный в первой половине двухтысячных. В этом проекте все базировалось на классах с одним методом, в котором происходило все: и работа с логикой, и вывод интерфейса (view) и обращения к базе, при чем, sql был прям там же между командами print "<table>";
Нетрудно догадаться, что я сильно облегчил жизнь бекэнд-разработчиков, для начала вынеся вывод верстки в шаблоны. Для этого я использовал уже готовый и довольно популярный шаблонизатор twig. Это было несложно и быстро, так что я даже не особо и выделял время на рефакторинг. Следующим шагом по-моему мнению нужно было что-то сделать с запросами к базе данных, в конце концов, MVC не зря так популярна у нас в веб. Насмотревшись на Симфони и Ларавел, я решил, что и здесь подход с использованием ORM отлично впишется. Поможет вынести работу с Базой Данных и оставить пока еще не-до-контроллерам только работу уже с полученными данными. Логично и совершенно правильно использовать уже существующие решения. Поэтому перво-наперво я ринулся в packagist посмотреть, какие альтернативы у меня есть кроме Docktrine, но хорошенько подумав, пришел к неутешительному выводу, что это не столь важно. Дело в том, что в этом проекте была довольно необычная структура данных. Такого я не встречал нигде более, хотя я работал с MODx :) Передо мной встала проблема: использовать популярные open-source ORM так, как я хочу не получится, ну, по крайней мере это будет то еще приключение. Так я решился на создание велосипеда. Немного про то, что же я сделал Да, я решил, что напишу ORM на PHP с нуля (нет, ну идеи и концепции перенятые у того же Docktrine у меня-то были) специально для этого проекта, да так, чтобы это работало со структурой данных. Ведь это рабочий сайт, и никто не был готов выделять ресурсы программистов на задачи «переписать все с нуля с нормальной структурой БД». Праотцы основавшие эту CMS создали 2 типа объектов, при чем один из них еще и делился на внутренние «типы данных»: ресурсы, у которых есть даты, ссылки, разные типы текста, изображения и еще ряд хранились в 2 таблицах, но были и объекты, хранящиеся в одной таблице, их думаю можно назвать системными данными. Я не хотел, чтобы применяя обращения к моделям, приходилось бы думать о джоинах, или хотя бы постараться сократить такие моменты до минимума. Поэтому я решил, что модели должны быть двух типов: для одно-табличных объектов и для основных двух-табличных. Так как у этих Моделей-классов много общих методов, тот же ORDER BY или LIMIT, поэтому каждый базовый класс, на основании которого и будут создаваться конкретные Модели, я наследовал от общего Абстрактного класса. Как можно видеть из дерева, я так же добавил поддержку разных типов Баз Данных, что в данном случае избыточно. Но я в тот момент вошел в «поток» и творил :). Также очень правильным в данном случае шагом явилось, то что я делал это на базе PDO, ибо использовавшийся в коде php-mysql не позволял переводить сайт на седьмую версию языка, а это хотелось исправить на корню, как говориться. $element = (new Model())->getOne($id);
Благодаря тому, что я хорошенько разобрался в логике структуры Базы данных, у меня получилось сделать поиск и получение ресурса только по его ID, даже не зная каким внутренним типом данных обладает ресурс, что было обязательно при старом подходе. Настоящая объектная работа с данными, и мы забываем об sql в коде. Заключительные абзацы... Эта работа принесла 2 неожиданных для меня поворота. Во-первых, я попытался все написать сразу в виде кода, и ничего не получилось. Мне пришлось взять ручку, блокнот, выйти на природу и под щебет воробьев и жужжание пчел сначала нарисовать, что я хочу получить, как это будет связано, какие мне нужны классы, и как это будет вызываться в коде «контроллеров». Кстати, потом реализация отличалась от изначальных зарисовок совсем незначительно. Так что, если программист ничего не кодит, это еще не значит, что он ничего полезного не делает. Во-вторых, я справился очень быстро, многие бизнесы не любят, когда программисты тратят время на всякие не понятные рефакторинги. Я реализовал весь проект в течении примерно недели, параллельно занимаясь поставленными задачами по внедрению новых features. Теми плюсами, о которых я заявлял в начале статьи я отмечу: последовательность и постепенность замены уже существующего кода на работающем проекте, а значит и отсутствие необходимости выделять больше времени на переход, рефакторинг кода в рамках поступающих задач. На этом откланяюсь, благодарю за чтение. =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 22:29
Часовой пояс: UTC + 5