Посоветуйте как правильно спроектровать каркас сервиса обмена графическими изображениями. Трудно представить архитектуру web-приложения, после разработки windows-приложений. Если бы под windows начал бы так(в скобках классы): Есть страница(Page), она включает навигацию (MainMenu, HeaderMenu, Navigation) и содержимое(Content), которое включает коллекцию фотографий(FotoCollection) и т.д. С этим никаких проблем, но как выглядит архитектура на php5 представляю смутно. Помогите разобраться, также буду рад примерам удачных архитектур с паттернами проектирования и кодирования
Полагаю, что начинать проектирование нужно не с объектов и классов, а с операций, которые будут доступны пользователям. Опишите, какие действия может совершать пользователь при использовании портала. Так же укажите и действия портала, которые важны для пользователя.
Возможно, эти операции станут очевидными после того, как Вы распишите несколько вариантов использования (use cases).
Здравствуйте, Кирилл Лебедев, Вы писали:
КЛ>Здравствуйте, SpLove,
КЛ>Полагаю, что начинать проектирование нужно не с объектов и классов, а с операций, которые будут доступны пользователям. Опишите, какие действия может совершать пользователь при использовании портала. Так же укажите и действия портала, которые важны для пользователя.
КЛ>Возможно, эти операции станут очевидными после того, как Вы распишите несколько вариантов использования (use cases).
КЛ>После этого можно будет говорить об архитектуре.
Я согласен с вами. Я знаком с циклом проектирования, просто думаю основная проблема различное мышление web архитекторов и архитекторов системного ПО. Вот, что нужно реализовать:
— регистрацию пользователей;
— механизм аутентификации зарегистрированных пользователей;
— добавление нового изображения (загрузка на сервер);
— просмотр списка всех загруженных пользователями изображений;
— просмотр детальной информации о каждом изображении с возможностью оставить свой комментарий и оценить его по шкале от 1 до 5;
— просмотр информации о выбранном пользователе.
Здравствуйте, SpLove, Вы писали:
SL>Я согласен с вами. Я знаком с циклом проектирования, просто думаю основная проблема различное мышление web архитекторов и архитекторов системного ПО. Вот, что нужно реализовать:
Думаю, это не основная проблема. Мне кажется, что сначала нужно построить функциональную модель программы, затем — распределить функции по сущностям, а уж потом — думать о реализации.
SL> — регистрацию пользователей; SL> — механизм аутентификации зарегистрированных пользователей; SL> — просмотр информации о выбранном пользователе.
Группа функций 1. "Работа с пользователями"
SL> — добавление нового изображения (загрузка на сервер); SL> — просмотр списка всех загруженных пользователями изображений; SL> — просмотр детальной информации о каждом изображении с возможностью оставить свой комментарий и оценить его по шкале от 1 до 5;
Группа функций 2. "Работа с изображениями"
Из приведенного Вами перечня функций можно выделить две группы:
Группа 1. "Работа с пользователями" Группа 2. "Работа с изображениями"
Эти группы можно детализировать:
Работа с пользователями:
1) Регистрация нового пользователя.
2) Удаление зарегестрированного пользователя.
3) Аутентификация зарегестрированного пользователя.
4) Просмотр информации о зарегестрированном пользователе.
5) Редактирование информации о зарегестрированном пользователе.
6) Посылка сообщения другому зарегестрированному пользователю.
7) Просмотр сообщений, присланных зарегестрированному пользователю.
8) Удаление сообщений, присланных зарегестрированному пользователю.
9) Отсылка предупреждения зарегестрированному пользователю.
10) Просмотр предупреждений, присланных зарегестрированнолму пользователю.
11) Оценка зарегестрированного пользователя.
12) Изменение рейтинга зарегестрированного пользователя.
13) Удаление рейтинга зарегестрированного пользователя.
14) Добавить друга.
15) Удалить друга.
16) Просмотреть список друзей.
17) Посмотреть конкретного друга.
18) Попроситься кому-то в друзья.
14) И т.д. Дополните этот список.
Работа с изображениями:
1) Добавление изображения. Куда? Очевидно, в альбом.
2) Удаление изображения. Откуда? Очевидно из альбома.
3) Вывод — необходимы альбомы. Начинаем список с начала...
1) Создание нового альбома.
2) Удаление существующего альбома.
3) Назначение/изменение прав доступа к альбому.
4) Открытие существующего альбома:
а) для просмотра;
б) для модификации.
5) Добавление фотографии в альбом:
а) с компьютера пользователя;
б) из того же альбома пользователя;
в) из другого альбома пользователя;
г) из альбома другого пользователя;
д) с постороннего интернет-сайта;
е) и т.д.
6) Изменение положения фотографии в альбоме.
7) Удаление фотографии из альбома.
8) Просмотр комментариев к альбому.
9) Добавление комментария к альбому.
10) Удаление комментария из альбома.
11) Просмотр комментариев к фотографии.
12) Добавление комментария к фотографии.
13) Удаление комментарии к фотографии.
14) Оценка альбома.
15) Просмотр оценки альбома.
16) Обнуление рейтинга альбома.
17) Отказ от участия в рейтинге.
18) Оценка отдельной фотографии.
19) Просмотр оценки отдельной фотографии.
20) Обнуление рейтинга фотографии.
21) Отказ от участия в рейтинге.
22) Записать альбом в фавориты.
23) Удалить альбом из фаворитов.
24) Просмотреть список фаворитов.
25) Изменить положение альбома в фаворитах.
26) Создать подкатегорию в фаворитах.
27) Переместить или скопировать альбом в подкатегорию.
28) И т.д. Дополните этот список.
Здравствуйте, SpLove, Вы писали:
SL>Посоветуйте как правильно спроектровать каркас сервиса обмена графическими изображениями. Трудно представить архитектуру web-приложения, после разработки windows-приложений.
Начинай с проектирования БД. Это главный компонент в подобных приложениях. А после и до классов доберешься.
Здравствуйте, DerBober, Вы писали:
DB>Начинай с проектирования БД. Это главный компонент в подобных приложениях. А после и до классов доберешься.
Нет. В таких проектах главный вопрос: Сколько будет народу.
Ибо пока на него не ответишь ничего не спроектировать.
Ибо база для 100 и для 100 тысяч пользователей это совершенно разные базы. Те просто ничего общего.
Так же отдельный очень интересный вопрос: как хранить фотографии так что бы их не потерять? В базе нельзя. База тонны блобов не выдержит. Да и раздавать из базы занятие не быстрое, а раздавать нужно много и быстро.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
DB>>Начинай с проектирования БД. Это главный компонент в подобных приложениях. А после и до классов доберешься. WH>Нет. В таких проектах главный вопрос: Сколько будет народу. WH>Ибо пока на него не ответишь ничего не спроектировать. WH>Ибо база для 100 и для 100 тысяч пользователей это совершенно разные базы. Те просто ничего общего.
Ну ну. Пока вы наберете первую тысячу пользователей все приложение успеете несколько раз переделать. Getting Real / Scale Later А преждевременная оптимизация, как известно, есть корень всех бед.
А ежели переделываете уже раскрученный сервис (фликер например) с гарантированными тысячами/миллионами пользователей, то таких вопросов возникать не должно.
Здравствуйте, DerBober, Вы писали:
DB>Ну ну. Пока вы наберете первую тысячу пользователей все приложение успеете несколько раз переделать.
Это зависит от того насколько хорошо работают маркетойды. И сколько денег есть на рекламу.
Если маркетойды хорошие и деньги на рекламу есть то десятки тысяч песетителей может быть в день запуска.
Но маркетойды должны быть очень хорошими.
Вот по этому при наличии хороших маркетойдов и денег на рекламу приходится запускать сервисы сразу на кластере из десятка машин (ибо лучше с запасом чем просесть по производительности в первый же день... да и в любом случае сервис еще долго придется тюнить чтобы реальную нагрузку держал...), и архитектура кластера делается сразу с возможностью масштабирования близкой к линейной. Также сразу закладывается реплекация в реальном времени ибо бекапить массовые сервисы на которых пользователи генерируют гигабайты контента в день задача практически не решаемая. По этому приходится изобретать другие схемы сохранения данных.
Плюс есть еще масса проблем которые нужно решить...
DB>А преждевременная оптимизация, как известно, есть корень всех бед.
Фраза правильная только не в тему.
Короче пока не ответишь на вопрос: Сколько будет народу? (Нужен прогноз по крайней мере на год.)
К разработке такой системы даже не подходи.
Если прогноз будет до тысячи посетителей в день то можно делать как угодно.
Если больше то...
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
DB>>Ну ну. Пока вы наберете первую тысячу пользователей все приложение успеете несколько раз переделать. WH>Это зависит от того насколько хорошо работают маркетойды. И сколько денег есть на рекламу. WH>Если маркетойды хорошие и деньги на рекламу есть то десятки тысяч песетителей может быть в день запуска. WH>Но маркетойды должны быть очень хорошими.
Ага. И маркетологи золотые и деньги есть и вообще все шоколадно. Непонятно только откуда при таких раскладах подобные вопросы у разработчиков возникают. (Не хочу никого обидеть. Честнослово.)
WH>Короче пока не ответишь на вопрос: Сколько будет народу? (Нужен прогноз по крайней мере на год.) WH>К разработке такой системы даже не подходи.
Никто не спорит с важностью вопроса о предельных нагрузках. Но по любому в основе будет БД. Даже если сами фотки лежат в ФС. Когда оптимизировать сервис под большие нагрузки это уже их проблема. Можно и сразу если бюджет позволяет.
Прежде всего, тебе следует свыкнуться с мыслью, что каждая страница сайта — изолированный скрипт. То есть, нет единой точки входа в приложение; каждая страница — отдельная точка входа. А учитывая тот печальный факт, что PHP — это просто скриптовый язык (запустился по HTTP-запросу — отработал — завершился, никаких фраерских выпендров типа резидентных многопоточных приложений и in-memory caches), то вся работа по инициализации приложения (коннект к базе, доставание данных о залогиненном пользователе из сохранённой сессии и проверке актуальности этого пользователя по базе, создание дерева объектов буде таковое использоваться) выполняется при каждом запуске скрипта, т.е. при каждом HTTP-запросе. Уже приятно, не так ли?
Для меня задача разработки сайтов на PHP всегда состоит из двух взаимосвязанных частей:
1. Разработка БД. (Реверанс в сторону WolfHound: с учётом требований о нагрузке, разумеется, хотя писать на PHP сервис под высокую нагрузку — это занятие для истынных ивзращенцев. Как раз вчера я в порядке самообразования проштудировал старый флейм stateful vs stateless за 2003 год... и подумал между делом: вот бы IT порадовался, случись ему писать на PHP... полный б#$%^ь stateless... Шучу, шучу. )
2. Определения множества HTTP-запросов пользователя, и разработка под каждый запрос своего отдельного скрипта — отдельной точки входа. Общий код инициализации приложения выносится в include-файл.
Никакой объектной модели предметной области нет. Каждый скрипт — именно скрипт, тупой и плоский. С голыми SQL-запросы. ООП я использовал только для написания удобных врапперов для парсинга HTTP-запросов, доступа к базе, генерации HTTP-ответов, ну и прочие utilities (типа поддержки блокировок). Вот типичный пример скрипта и генерируемого им ответа:
index.php
<?php
require_once(dirname(__FILE__) . '/_php/include_user.php');
$pageId = (int)$request->get('page');
if (!$pageId) {
$pageId = 1;
}
$r = $db->qrow("select * from {PREFIX}pages where id=?", array(0 => $pageId));
if (!$r) {
require_once(dirname(__FILE__) . "/404.php");
die();
}
$response->rowset('page', array('text' => 'xhtml'))->addRow($r);
$submenuParentId = $r['parentid'] ? $r['parentid'] : $r['id'];
$response->rowset('submenu', array('*' => 'attr'))->addDBRowset($db->query(
"select id, uri, menutitle from {PREFIX}pages where parentid=? order by sortorder",
array(0 => $submenuParentId)));
//$response->outputXML();
$response->outputHTML($config['design_path'] . "index.xsl");
?>
Вывод, если раскомментить outputXML() вместо outputHTML():
Метод outputHTML() просто применяет XSLT к этому XML-выводу. Очень удобно, между прочим.
Единственные task-specific объекты, которые у меня водились достаточно часто (когда выпадала возможность писать под транзакционный MySQL/InnoDB, а не MySQL/MyISAM), это функторы-транзакции, отрабатывающие внутри кода, перезапускающего транзакцию в случае deadlock (по одному функтору на точку входа, плюс механизм вызова функторов-"подпрограмм" с какими-то общими для нескольких скриптов операциями).
Объектную модель предметной области я создавал только один раз, когда сложность взаимосвязей между сущностями вышла из-под контроля. Нарисовал простенький ORM... (Ну очень простенький... не так давно в форуме "Веб-программирование" кто-то спрашивал про ORM на PHP, но мне своей кустарщиной стыдно было делиться... да и какой к чёрту ORM, если кеши пропадают при завершении скрипта?) И честно предупредил заказчика, чтобы он готовился покупать выделенный сервер и переписывать всё на JBoss.
Хочется верить, что я высказался достаточно понятно и с пользой. Туплю с утра, после вчерашнего сеанса самообразования.
Здравствуйте, DerBober, Вы писали:
DB>Ага. И маркетологи золотые и деньги есть и вообще все шоколадно. Непонятно только откуда при таких раскладах подобные вопросы у разработчиков возникают. (Не хочу никого обидеть. Честнослово.)
Так у меня и не возникает.
DB>Никто не спорит с важностью вопроса о предельных нагрузках. Но по любому в основе будет БД. Даже если сами фотки лежат в ФС. Когда оптимизировать сервис под большие нагрузки это уже их проблема. Можно и сразу если бюджет позволяет.
Тут проблема в том что нагрузки бывают разные. И БД тоже.
Есть нагрузки которые держит MySQL, есть нагрузки для которых нужен Oracle, а есть нагрузки для которых нужен MySQL.
Парадокс?
Оказывается нет.
В третьем случае просто делается своя БД под конкретную задачу при реализации который другие БД используются лишь как тупые таблички с индексами и ничего кроме плоских селектов и примитивных апдейтов по ним не делают. Плюс еще несколько фокусов.
Таким образом какая там БД с диском возится в очень широких приделах барабану.
Он задачка мягко говоря не тривиальная. Без особой нужды дешевле взять Oracle.
Вот и нужно определится какой вариант делать изначально.
А для этого нужен прогноз нагрузки как минимум на год.
А так "портал обмена фотографиями" завучит как "сферический конь в вакууме" ибо там могут быть и вариант 1 живущей на одной дохлой машине и вариант 3 живущей на кластере из современных серверов.
ЗЫ Большое железо — лохотрон. Кластеры рулят.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Дм.Григорьев, Вы писали:
ДГ>index.php
ДГ>
ДГ>$r = $db->qrow("select * from {PREFIX}pages where id=?", array(0 => $pageId));
ДГ> "select id, uri, menutitle from {PREFIX}pages where parentid=? order by sortorder",
ДГ>
Я прошу прощения, но что, в Пыхпыхе только так и делают, да? То есть прямо вот так вот SQL зашивают в код?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
HgLab: Mercurial Server and Repository Management for Windows
Здравствуйте, Нахлобуч, Вы писали:
Н>Я прошу прощения, но что, в Пыхпыхе только так и делают, да? То есть прямо вот так вот SQL зашивают в код?
Гы, а ты предлагаешь его из ресурсов грузить?
Всё определяется сложностью проекта. Мой подход, чрезвычайно удобный на небольших и средних проектах, на сложных не сработает (о чём я также отчитался).
Здравствуйте, Дм.Григорьев, Вы писали:
ДГ>Всё определяется сложностью проекта. Мой подход, чрезвычайно удобный на небольших и средних проектах, на сложных не сработает (о чём я также отчитался).
С этим я и не спорю. Но хранить SQL в коде совсем уж некошерно. Хотя бы и в ресурсы вынести -- всяко лучше будет.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
HgLab: Mercurial Server and Repository Management for Windows
Здравствуйте, Нахлобуч, Вы писали:
ДГ>>Всё определяется сложностью проекта. Мой подход, чрезвычайно удобный на небольших и средних проектах, на сложных не сработает (о чём я также отчитался). Н>С этим я и не спорю. Но хранить SQL в коде совсем уж некошерно. Хотя бы и в ресурсы вынести -- всяко лучше будет.
Чем же это лучше? Ты увеличиваешь сложность на пустом месте, разбивая вполне простой алгоритм скрипта на несколько слоёв, причём сильно связанных. В итоге ты только запутаешь код. Или по-твоему, часто возникает потребность менять крохотный кусочек единого алгоритма (текст SQL-запроса) без изменений в остальных частях (PHP-код, в т.ч. обработка result set)? В общем, в данном случае ты говоришь ерунду.
Здравствуйте, Дм.Григорьев, Вы писали:
ДГ>Чем же это лучше? Ты увеличиваешь сложность на пустом месте, разбивая вполне простой алгоритм скрипта на несколько слоёв, причём сильно связанных.
Сложность никто не увеличивал. Я ее просто перераспределил, вытащив не относящиеся к делу куски из одного модуля в другой. И понятность от этого ничуть не уменьшилась: заменив
$response->rowset('submenu', array('*' => 'attr'))->addDBRowset($db->query(
"select id, uri, menutitle from {PREFIX}pages where parentid=? order by sortorder",
array(0 => $submenuParentId)));
я сделал только лучше.
ДГ>В итоге ты только запутаешь код.
Как видишь, не запутал. Более того, этот код стало проще поддерживать и тестировать.
ДГ>Или по-твоему, часто возникает потребность менять крохотный кусочек единого алгоритма (текст SQL-запроса) без изменений в остальных частях (PHP-код, в т.ч. обработка result set)?
По-моему, изменение, затрагивающее одну часть системы (например, БД), не должно вызывать каскад изменений в остальных ее частях. А случается это, особенно в случае динамично развивающейся системы, очень и очень часто.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
HgLab: Mercurial Server and Repository Management for Windows
ДГ>>В итоге ты только запутаешь код. Н>Как видишь, не запутал. Более того, этот код стало проще поддерживать и тестировать.
Всё это очень красиво, очень объектно-ориентированно и концептуально очень правильно. Но к сожалению, в подавляющем большинстве веб-проектов (не отличающихся сложностью бизнес-логики) совершенно непрактично. И я здорово сомневаюсь, что твой код проще поддерживать и тестировать.
Прежде всего, по причине невозможности кеширования объектов между HTTP-запросами, и по причине отсутствия реализации Hibernate для PHP, все запросы приходится оптимизировать вручную. Раскладывать вручную оптимизированный запрос в "правильную" объектную модель — занятие для больших оригиналов. Нужны очень веские причины, чтобы заниматься подобным извращением. Я уже писал — таковые причины у меня нашлись только один раз за последние 5 лет. Подавляющее большинство сайтов не настолько сложны, и в них вполне достаточно описанного мною модульного подхода, в котором каждая точка входа — атомарная операция, вполне читабельная и легко сопровождаемая. Декомпозировать такие скрипты дальше не имеет смысла.
Далее. Все результаты SQL-запросов где-то используются, верно? Так случилось, что большинство результатов просто отдаётся клиенту (исключения — какие-то проверки перед модификацией базы). А теперь смотри: результаты используются в XSLT-преобразовании. Выполнение XSLT-скриптов я по возможности (в зависимости от значения USER AGENT) отдаю на откуп клиенту, чтобы уменьшить нагрузку на сервер и трафик. И поэтому я должен очень внимательно подходить к тому, какие столбцы я отдаю в XML-ответе. Юзеры, админы и незалогинившиеся посетители очень часто получают совершенно разные наборы столбцов. В результате я вынужден либо генерировать SQL-запрос динамически, либо дублировать его в разных вариациях для разных точек входа и разных юзеров/админов/прочих. И как по мне, гораздо проще отслеживать все эти ньюансы и зависимости в контексте одного скрипта (где они как на ладони), чем плодить тьму методов (или параметризованные методы):
С предложенным тобой делегированием сам скрипт index.php становится неприятным промежуточным звеном между index.xsl и сильно, но неочевидно связанных с ним методов каких-то объектов-менеджеров. А уж если ты попытаешься вынести генерацию, скажем, списка пользователей по сложному условию (или любой другой нетривиальный SQL-запрос) из search.php (где он выглядит вполне уместно) в какой-нибудь $userManager, то в итоге получишь совершенно расчудесный вызов типа $userManager->getUsersByConditionForAdmin($twenty, $filter, $parameters, $which, $are, $impossible, $to, $remember, $and, $very, $hard, $to, $specify, $without, $mistake). Ну и нахрена козе боян?
Короче говоря, я просто использую другой способ декомпозиции — модульный, а не объектный. И на простых и средней сложности проектах, в условиях налагаемых языком PHP ограничений, этот способ гораздо проще и эффективнее объектов. У меня было предостаточно времени на эксперименты — могу честно сказать, что данный подход выстрадан на не одном десятке проектов (включая контент-сайты, службы знакомств с форумумами, блогами и интернет-магазинами — типовые задачи, и в целом далеко не самые тривиальные). И я готов поспорить, что твои ООП-заморочки (так называемые "упрощения") приведут только к усложнению кода и существенному снижению его эффективности.
Здравствуйте, Дм.Григорьев, Вы писали:
ДГ>Прежде всего, по причине невозможности кеширования объектов между HTTP-запросами, и по причине отсутствия реализации Hibernate для PHP, все запросы приходится оптимизировать вручную.
Во-первых, кэширование можно и самому (если уж очень припрет) сделать. Во-вторых, не вижу связи между кэшированием и необходимостью оптимизации запросов.
ДГ>Раскладывать вручную оптимизированный запрос в "правильную" объектную модель — занятие для больших оригиналов. Нужны очень веские причины, чтобы заниматься подобным извращением.
Частично соглашусь. Вручную гидрировать "правильную" объектную модель и правда занятие не из приятных. Однако же в случае, когда классы Domain Model представляют собой просто DTO на стероидах (чего достаточно для простых приложений), делать это, по-моему, не так и сложно.
ДГ>Далее. Все результаты SQL-запросов где-то используются, верно? Так случилось, что большинство результатов просто отдаётся клиенту (исключения — какие-то проверки перед модификацией базы). А теперь смотри: результаты используются в XSLT-преобразовании.
Сам с таким подходом не сталкивался, но сдается мне, что при более-менее сложной верстке этот XSLT будет феерически объемным. Плюс в HTML редакторе его так просто и не посмотришь.
Если я правильно понял логику, то MenuManager получается очень перегруженным и у него образуется слишком большая зона ответственности — и получение объектов из БД, и разруливание вопросов с полномочиями. А сие не есть правильно .
Кроме того, вот это:
ДГ>И поэтому я должен очень внимательно подходить к тому, какие столбцы я отдаю в XML-ответе. Юзеры, админы и незалогинившиеся посетители очень часто получают совершенно разные наборы столбцов. В результате я вынужден либо генерировать SQL-запрос динамически, либо дублировать его в разных вариациях для разных точек входа и разных юзеров/админов/прочих.
тоже смущает. Насколько я могу понять из приведенного тобой выше по ветке кода (типа, "select id, uri, menutitle from {PREFIX}pages where parentid=? order by sortorder"), ты очень сильно завязываешься на имена столбцов — они у тебя есть и в тексте запроса, и во всяких индексаторах, и в XSLT. По мне, так это дюже нехорошо.
Если же использовать какие-никакие классы-DTO, то в общем случае получается, что для разных типов пользователей (админы, простые смертные и т.д.) требуются разные DTO с разным набором полей. Получаем экспоненциальный рост количества классов.
Получается, что для упрощения своей же жизни все вопросы отображения и сокрытия той или иной информации должны быть решены на уровне View'а (если говорми про MVP/MVC). Но тогда выходит, что либо придется использовать какой-нибудь шаблонизатор (из оных для PHP знаю только Smarty), либо делать все XSLT-преобразования на сервере.
ДГ>С предложенным тобой делегированием сам скрипт index.php становится неприятным промежуточным звеном между index.xsl и сильно, но неочевидно связанных с ним методов каких-то объектов-менеджеров.
Это не объекты-менеджеры с ним связаны, а index.php связан с ними -- а это большая разница. И связь эта, при продуманной архитектуре, очевидна и несильна.
ДГ>А уж если ты попытаешься вынести генерацию, скажем, списка пользователей по сложному условию (или любой другой нетривиальный SQL-запрос) из search.php (где он выглядит вполне уместно) в какой-нибудь $userManager, то в итоге получишь совершенно расчудесный вызов типа $userManager->getUsersByConditionForAdmin($twenty, $filter, $parameters, $which, $are, $impossible, $to, $remember, $and, $very, $hard, $to, $specify, $without, $mistake). Ну и нахрена козе боян?
Вот с этим соглашусь -- сам для себя никак не могу толком сформулировать подход решения этой проблемы. Получается либо Query By Example, либо класс-генератор запросов (строго типизированный) либо да, такой вот огромный метод.
ДГ>Короче говоря, я просто использую другой способ декомпозиции — модульный, а не объектный. И на простых и средней сложности проектах, в условиях налагаемых языком PHP ограничений, этот способ гораздо проще и эффективнее объектов.
Быть может. Насчет эффективности только я сильно не согласен. Разницы между 0.05 секунды и 0.5 секунды (такой оверхед надо еще постараться получить) пользователь вряд ли заметит.
ДГ>У меня было предостаточно времени на эксперименты — могу честно сказать, что данный подход выстрадан на не одном десятке проектов (включая контент-сайты, службы знакомств с форумумами, блогами и интернет-магазинами — типовые задачи, и в целом далеко не самые тривиальные).
Ну неужто в интернет-магазинах и службах знакомств ты текст запроса тоже в коде писал?
ДГ>И я готов поспорить, что твои ООП-заморочки (так называемые "упрощения") приведут только к усложнению кода и существенному снижению его эффективности.
Эффективность -- это в смысле быстродействие? А как же преждевременная оптимизация -- корень всех зол?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
HgLab: Mercurial Server and Repository Management for Windows