Forum Webscript.Ru

Программирование => Perl => Тема начата: 2NetFly от 19 Декабря 2004, 22:29:02

Название: CMF на перле
Отправлено: 2NetFly от 19 Декабря 2004, 22:29:02
Занимаюсь разработкой сбжа на основе MVC model 2 с использованием паттернов front controller, application controller, template view и пр. Сравнить можно с maypole (perl), OpenInteract (perl), php-mvc (php), WACT (php), Struts (Java). Реализация бизнес логики и логики представления может быть произвольная, сам использую самописные классы для модели (аналог Class::DBI) и TT2 для view.

Концепция более или менее продумана, есть упрощенная реализация в черновом варианте. Дополнительно написан механизм валидации (аналог WACT-ского). В результате хочу получить что-то более прозрачное и простое, чем OpenInteract, более функциональное и правильное (с точки зрения ООП), чем maypole и содержащее некоторые хорошие идеи из Struts.

Пишу в свободное от работы время, один не то что бы не справляюсь, просто некоторые спорные моменты обсудить не с кем, зачастую очень много времени уходит на то, чтобы увидеть очевидные для других вещи. Если кто-то занимается решением подобной задачи, было бы интересно поделиться опытом или, что еще лучше, заняться разработкой совместного решения.
Название: CMF на перле
Отправлено: 2NetFly от 21 Декабря 2004, 12:53:31
Эм, неужели никто таким не занимается? Или я отстал от жизни и у всех есть готовые системы? =)
Название: CMF на перле
Отправлено: NeoNox от 21 Декабря 2004, 13:13:51
Цитировать
2NetFly:
Эм, неужели никто таким не занимается?

Вероятно нет. С удовольствием почитал http://maypole.perl.org/, нашел спорные моменты, но еще не готов ввязываться в дискуссию.
Ты бы написал краткий обзор своего виденья CMF, может и единомышленники нашлись.
Название: CMF на перле
Отправлено: 2NetFly от 21 Декабря 2004, 14:29:01
Maypole, имхо, лучший perl MVC фреймворк. Впрочем, это неудивительно, учитывая то, кто его писал и поддерживает =)

Лично мне в нем не нравится специфический perl-ООП стиль написания, концентрация всей логики в одном классе, тесная интеграция с Class::DBI, отсутствие встроенного механизма валидации и многие мелочи.

Касательно моего виденья CMF - ничего революционного и новаторского в нем нет. Просто после написания и использования нескольких собственных неудачных систем, изучения литературы по данной теме, а так же изучения существующих решений, у меня сформировалось собственное мнение и виденье реализации, воплощением в жизнь которой и я занимаюсь. Вечером я постараюсь в двух словах рассказать, как я представляю себе CMF.
Название: CMF на перле
Отправлено: 2NetFly от 21 Декабря 2004, 16:54:16
Появилось свободное время, посему постараюсь описать в двух словах CMF так, как вижу ее я.

Как я уже писал выше, CMF разрабатывается на основе MVC model 2 паттерна, что подразумевает выделение трех слоев: модели, представления и контроллера. Реализация модели т.е. бизнес логики может быть произвольная т.к. доменные объекты должны быть отделены от преставления и контроллера. CMF не должна накладывать никаких ограничений на реализацию преставления: может использоваться как один из шаблонизаторов типа Template Toolkit или HTML::Template, embeded-технология вроде Mason, так и xml + xlst.

Для реализации контроллера применятся паттерн Front Controller, который состоит из самого обработчика и команд. Для маппинга (связи между url и соответствующими командами) используется глобальный для всего проекта xml-конфигурационный файл. Пример (упрощен для понимания):




Все запросы проходят через контроллер (я для этих целей использую mod_rewrite), который выполняет следующие действия:
1. Считывает глобальный для всего проекта конфигурационный файл.
2. Создает экземпляры объектов классов Request, Displayer, Response, Context.
3. Используя методы созданных классов, парсит запрос и определяет table и action, сохраняет параметры post, get и т.д.
4. Парсит xml конфигурационный файл и на основе table и action находит информацию о соответствующем классе-команде.
5. Создает экземпляр объекта класса-команды и вызывает методы execute созданного объекта. Класс-команда может создавать и манипулировать доменными объектами, регистрировать данные, которые будут доступные во View и т.д. Класс-команда посредством специального метода должен определить, какой  view будет работать после его завершения.
6. Управление передается объекту класса Displayer, который, на основе данных установленных командой, получает нужные шаблоны, процессит их и пишет результат в Response.
7. Выводит данные пользователю.

Response похож по функциональности на соответствующий класс в Struts и php-mvc. Displayer является аналогом класса View в maypole и путем наследования и добавления функциональности может быть "прикручен" к любому шаблонизатору.

Помимо всего этого частью системы нужно сделать:
1. Механизм валидации параметров и вывода пользовательских ошибок. Я уже сделал подобный механизм на основе правил.
2. Хранилище сообщений и языковых настроек и поддержка многоязычности.
3. CRUD класс, который будет базовым для всех простых классов модели.
4. Набор common классов-команд таких как Add, Delete, Create, View, с возможностью конфигурирования посредством xml-конифга.

И много-много мелочей, вроде системы обработки ошибок, логирования и пр.

Многое из описанного выше уже готово и если кто-нибудь захочет принять участие в разработке, с радостью покажу код - это будет лучшим описанием.
Название: CMF на перле
Отправлено: 2NetFly от 08 Марта 2005, 14:54:44
Решил поднять тему. Ни у кого не возникло желания поучаствовать? =) Как я уже писал выше, лучшей помощью будет участие в обсуждении тех или иных вопросов, связанных с системой.
Название: CMF на перле
Отправлено: NeoNox от 08 Марта 2005, 23:10:01
2NetFly уважаю твое стремление.
Можно тебя попросить обрисовать сферу использования Maypole? Также, расскажи пожалуйста про степень уверенности в 100% корректности и лишенности мемори-ликов кода сопутствующих модулей.
Спасибо.
Название: CMF на перле
Отправлено: 2NetFly от 09 Марта 2005, 10:31:29
Насчет сферы использования Maypole я ничего сказать не могу - я эту систему в серьезных проектах не использовал. Поставил, покопался в коде, перечитал всю документацию и статьи на Perl.com, но ничего серьезного не делал. Хотя, я думаю, что как и все MVC CMF она может быть использована практически в любом серьезном веб-приложении. На предыдущей версии своей системы, которая была очень далека от идеала, у меня были написаны стандартный портал с новостями, статьями, фотогалереей и пр., приличный mp3 архив и музыкальная энциклопедия и несколько биллинговых систем различного уровня сложности.

Я несколько месяцев уделил изучению различных систем на разных языках и всевозможных книг / статей по данному вопросу и на этот раз хочу сделать все правильно и надолго =) Помимо стандартных фич хочу включить в систему:
- механизм валидации пользовательских данных (параметров);
- механизм хранения и отображения сообщений об ошибках, с поддержкой многоязычности;
- CRUD класс, реализующий ORM для простой таблицы;
- DBAL на основе DBI;
Название: CMF на перле
Отправлено: 2NetFly от 09 Марта 2005, 10:51:21
Вот небольшой пример маппинга одного действия (очень упрощенный):


                name="reg"
            className="Reg"
            classPath="module/User/class"
            successAlias="..."
            failedAlias="..."
            failedValidateAlias="..."
            >
       
           
               
                    login
               

               
                    ^\\w+$
               

           


           
               
                    password
               

               
                    ^\\w+$
               

           

           
           
               
                    email
               

           


           
               
                    password
                    repassword
               

           


       

       
       
            user.password_ne_repassword
            user.password_invalid
            user.login_invalid
            user.email_invalid
       

       
       
         
       

   


Название: CMF на перле
Отправлено: 2NetFly от 09 Марта 2005, 10:53:54
На самом деле XML - это обертка для класса валидатора, при необходимости проверка может быть реализована в самом классе обработчике. Но это все так, частные случаи.
Название: CMF на перле
Отправлено: Макс от 09 Марта 2005, 13:29:18
Цитировать
2NetFly:
2. Создает экземпляры объектов классов Request, Displayer, Response, Context.

а что делает объект Context ? (можно просто ссылкой)
Цитировать
2NetFly:
- механизм валидации пользовательских данных (параметров);
......
 - CRUD класс, реализующий ORM для простой таблицы;

То есть валидация и CRUD-операции не будут находиться в одном (доменном) классе ?

PS
Цитировать
2NetFly:
Я несколько месяцев уделил изучению различных систем на разных языках и всевозможных книг / статей по данному вопросу и на этот раз хочу сделать все правильно и надолго =)

Ruby on Rails смотрел ? Если смотрел, то интересно твое мнение.
Название: CMF на перле
Отправлено: 2NetFly от 09 Марта 2005, 14:11:54
Цитировать
а что делает объект Context ? (можно просто ссылкой)

Это контейнер (возможно, лучше было бы его именно так назвать) для других объектов плюс в нем собраны методы, которым я не нашел места в других классах. Проще всего объяснить кодом:

my $c = WCP::Context->new();
$c->{displayer} = WCP::Displayer::TT->new();
$c->{config} = WCP::Config::Base->new();
$c->{response} = WCP::Response->new();
$c->{request} = WCP::Request::CGI->new;
my $fc = WCP::FC->new();
$fc->process($c);

Цитировать
То есть валидация и CRUD-операции не будут находиться в одном (доменном) классе ?

Я планирую сделать валидацию параметров, полученных от пользователя, отдельным этапом (как в Struts). Т.е. сначала выполняется метод validate класса-команды и лишь затем, в случае успеха, execute. Т.е. при передаче параметров в доменный класс, последний знает, что параметры гарантировано проверены. С точки зрения безопасности это не лучшее решение, но зато очень гибкое. Механизм валидации почти такой же, как в WACT. Вот пример (то что под оберткой):

sub validate
{
    my ($self, $c) = @_;
   
    my $validator = WCP::Validator->new();
    my $md = WCP::Validator::MessageDictionary->new();
   
    $validator->addRule(\'title\', \'title\', \'Length\', [3, 10]);
    # То же самое, что $validator->addRule(\'title\', \'title\', WCP::Validator::Rule::Length->new(3, 10));
    $validator->addRule(\'title\', \'title\', \'Regexp\', [ \'^[a-zA-Z ]+\' ]);
    $validator->addRule(\'categoryid\', \'categoryid\', \'Regexp\', [ \'^\\d+$\' ]);
    $validator->addRule(\'type\', \'type\', \'Regexp\', [ \'^\\d+$\' ]);
   
    $md->registerMessage(\'Недопустимые символы.\', \'REGEXP_FAILED\');
    $md->registerMessage(\'Слишком короткий.\', \'LENGTH_MIN\');
    $md->registerMessage(\'Слишком длинный.\', \'LENGTH_MAX\');
   
    my %params = $c->request->getParams();
    if ($validator->validate(\\%params)) {
        return 1;
    } else {
        $c->setErrors($validator->getMessageList($md));
        return;
    }
}

Принцип работы прост: при регистрации правила первым параметром указывается имя поля (или ссылка на массив имен полей), которые участвуют в проверке, вторым - имя группы, а третьим и четвертым - имя класса и параметры для конструктора. Правило имеет метод validate, которое возвращает булево значение. Если валидация не удалась, посредством метода getCodes можно получить массив констант, обозначающих неудавшиеся проверки (например, LENGTH_MIN, LENGTH_MAX и т.д.). После регистрации произвольного числа правил и валидации, в случае возникновения ошибок для каждой группы сохраняется массив (в порядке, указанном при регистрации правил) кодов ошибок. Грубо говоря:

{
    \'title\' => [
          \'LENGTH_MIN\',
          \'REGEXP_FAILED\'
     ],
     \'categoryid\' => [
          \'REGEXP_FAILED\'
     ]
 };

Потом в словарь сообщений добавляются тексты: или общий для каждого типа ошибки (например, для REGEXP_FAILED "Недопустимые символы") или для каждого типа ошибки и группы (например для title + REGEXP_FAILED "Поле title содержит недопустимые символы").

Отображение выполняется при помощи следующего шаблона:

[% INCLUDE header.tpl title="Добавление документа"%]

[% BLOCK field %]
  [% IF errors.${fld_name} %]
   
   
[% errors.${fld_name}.0 %]

   
  [% END %]    
   
  [% IF errors.${fld_name} %]
[% fld_title %]:

  [% ELSE %][% fld_title %]:[% END %]
   
[% END %]


 

[% INCLUDE field
  fld_name = "title"
  fld_title = "Название"
%]    
   
     
   
[% INCLUDE field
  fld_name = "categoryid"
  fld_title = "Категория"
%]    
     
   
[% INCLUDE field
  fld_name = "type"
  fld_title = "Тип"
%]    
     
   
   
   
   
 

       
     

       
     

       
     



Т.е. если при заполнении какого-то поля были допущены ошибки, поле выделяется цветом, а под ним пишется текст первой ошибки (или можно вывести список всех ошибок сразу же).

Все немного сумбурно, т.ч. если будут какие-то конкретные вопросы - спрашивайте. По валидатору у меня есть документация, немного доработаю и выложу.
Название: CMF на перле
Отправлено: 2NetFly от 09 Марта 2005, 18:20:08
Решил выложить на обозрение весь механизм валидации.

По правилам оформил небольшой обзор:
Документация по правилам (http://feotast.net/wcp/rule.html)
Но правила - это только основа всего механизма. Остальное продокументирую потом, а пока можно скачать архив (http:// [url=http://feotast.net/wcp/wcp.rar) и посмотреть на реализацию. Код довольно чистый, я вложил пример т.ч. все должно быть понятно. Имейте в виду, что это черновой вариант =) Работа с сообщениями и MessageDictionary точно будут перерабатываться.
Название: CMF на перле
Отправлено: 2NetFly от 10 Марта 2005, 00:41:01
Повесил блог, писать буду там, а комментировать можно здесь.

Блог: http://2netfly.com/blog/ .
Название: CMF на перле
Отправлено: 2NetFly от 10 Марта 2005, 15:56:19
Отписал довольно много аналитики, сумбурно, конечно, но общие принципы уже уловить можно.
Название: CMF на перле
Отправлено: Макс от 10 Марта 2005, 17:39:37
По поводу http://2netfly.com/blog/?p=6
1. По поводу get/set - методов.
Про set - согласен. А вот get-методы ИМХО могут быть полезны. Код буду приводить на ПХП (мне он  ближе)
Возьмем типичную новость. Ее надо показать на странице юзеру, ее надо показать в админке, возможно где-нибудь еще. Например дату новости на всех этих страницах надо привести к одному формату. В тексте новости надо символы перевода строк заменить на
 а теги <> на & lt; & gt;
Если все это делать в шаблонах или ручкми после получения, то получиться избыточный код. Поэтому имхо удобнее сделать get-методы :
 function getDate() {
    return date(\'Y.m.d\', $this->fields[\'date\']);
}
а вшаблонах вызывать $news->getDate(); - хотя это уже зависит от уровня представления.

2. Все-таки в 95% случаев данные добавляются через POST.
 if (POST_METHOD) {
      if ($news->add()) {
            redirect(\'news_added.php\');      
      }  else {
             $errors = $news->errors; // получаем массив ошибок
      }
} метод add() сам загружает данные из пост, проверяет и записывает в БД (я все таки за проверку данных внутри класса)

3. мне кажется более логичным такое разделение классов :
 - один базовый класс(DBObject) и все его наследники занимаются отображением одного объекта. В основном он занимается CRUD-операциями + по желанию (например если объектом является юзер, то занимается его авторизацией). Причем READ-операция делает только чтение одного объекта (не списка)
 
 - один базовый класс (DBObjectList)  и все его наследники занимаются работой со списком объектов. Это все выборки из БД и все что с этим связано - постраничная разбивка, определение кол-ва найденных объектов, некоторые манипуляции с полем ORDER BY.
while ($obj = &$list->getOne()) {
   /// $obj - объект типа DBObject
}


4. и немного о проблеме модификации класса при добавлении новых связей.
Я в своем классе сделал поле $_fields, в которое помещаются все неиспользованые данные. Например объект новостей получил хеш-массив:

 $fields = array(
   "id"=> 12,
   "subject"=>"....",
   "text"=>"....",
   "blablabla"=>"XXX",  /// <<<
   "date"=> "....")
Допустим объект новостей ничего не знает о поле "blablabla", тогда это поле и его значение будут помещены в $_fields (на всякий случай) и к нему я всегда смогу обратиться.
Теперь если мне в готовом проекте вдруг понадобилось подключить к новостям комментарии и выводить их кол-во, то я меняю запрос :
SELECT news.*, [b]COUNT(comments.*) as comments_amount[/b] FROM ..... LEFT JOIN .....
а в шаблоне напишу _fields[\'comments_amount\']);?>
Но эта фича скорее для "грязных хаков", чем для постоянного использования :)
Название: CMF на перле
Отправлено: 2NetFly от 10 Марта 2005, 18:43:38
Во-первых, спасибо за ответ, наконец-то появилась возможность подискутировать на интересную мне тему =) Во-вторых, если не сложно, продублируй свой ответ в блоге - его читаю пользователи других форумов, возможно они тоже захотят принять участие в дискуссии. Теперь ответы по пунктам.

1. Я довольно скептически отношусь к использованию объектов в шаблонах и, как следствие, к представлению, например, новости, как объекта. В моем понимании новость - это ассоциативный массив, ключи которого дублируют поля таблицы, и, если необходимо, некоторые дополнительные значения, которые предварительно устанавливаются доменным объектом. А список новостей - это массив таких хэшей. Может в будущем я изменю свое мнение, но сейчас мне кажется, что объектам в представлении не место (за исключением статических методов построения блоков информации).

Касательно замены определенных символов в некоторых полях, приведения даты к стандартному формату и прочего - я размышлял над этим, но пока не пришел к окончательному выводу, хотя уже вижу два пути реализации:
а) изменять данные непосредственно после выборки и хранить их в новом формате.
б) делать то же самое, но не в коде, а при помощи xml конфига. Пример подобного конфига был приведен в отчете о PHP конференции (доклад посвященный ORM).

2. У меня существует отдельный класс Request который занимается парсингом параметров и он умеет преобразовывать, например, /news/show/123/ в action=show&id=123. Использования такого класса упрощает модификацию обработки и пасинга параметров путем просто переопределения нужных методов.

3. Раньше все так и было. Все классы наследовали Object (в нем методы select, update, create, delete, getAll), зачастую в классах-наследниках указывался только путь к xml конфигурационному файлу (в нем определились короткие синонимы для полей, указывался первичный ключ, его тип и пр.), а так же был статический метод list (find) который занимался работой со списком. Однако вскоре стали появляться большие проблемы. Например, все документы я храню в одной таблице, информацию об авторах - в другой, иконку для документа - в третьей, информацию о источнике - в четвертой и т.д.. Я так и не смог придумать, как правильно реализовать метод выбора одной новости и списка новостей в этом случае и в какой класс его поместить. С одной стороны загромождать класс Document неправильно, с другой - больше эти методы и деть-то некуда.

Вот такой вот был запрос для списка (немного упрощенный =):

my $query = "
SELECT *
FROM $TBL{document}{_} AS doc
LEFT JOIN $TBL{author}{_} AS a ON a.$TBL{author}{id} = doc.$TBL{document}{authorid}
LEFT JOIN $TBL{category}{_} AS cat ON cat.$TBL{category}{id} = doc.$TBL{document}{categoryid}
LEFT JOIN $TBL{source}{_} AS s ON s.$TBL{source}{id} = doc.$TBL{document}{sourceid}" .
($self->SQLOrderBy($sparam->{OrderBy})) .
$self->SQLLimit(@{$sparam->{Limit}});


А так я вынес все методы отображения в отдельный класс и теперь доменные классы практически не подвергаются правке. Ну и в шаблоне это дело удобно использовать:


[% News::List("tmp_1", LimitForm => 0, LimitTo => 3, OrderBy => ‘date’, OrderType => ‘DESC’) %]

[% News::List("tmp_2", LimitForm => 3, LimitTo => 10) %]

tmp_1, tmp2 - это тройные шаблоны (альтернатива foreach).

Все, конечно, упрощенно. Можно обрабатывать ситуации, когда список пуст и т.д., но общая идея должна быть понятна.

Кстати,  весьма интересная реализация работы с шаблонами есть в WordPress (блоге). Я думаю что для PHP (с перлом другая история) шаблонизаторы типа смарти - это излишество.
Название: CMF на перле
Отправлено: Макс от 10 Марта 2005, 20:11:29
Цитировать
2NetFly:
Во-первых, спасибо за ответ, наконец-то появилась возможность подискутировать на интересную мне тему =)

ну насчет этого особо не радуйся, времени на обдумывание и дискуссию у меня мало. Я в последнее время мало ORM занимаюсь и нет/жаль свободного времени на это.

По поводу блога - подними эту тему к выходным, я все тексты туда переброшу. У тебя там какой-нибудь ББ-код есть для подсветки синтаксисиа ?

 
Цитировать
2NetFly:
 1. Я довольно скептически отношусь к использованию объектов в шаблонах и

Цитировать
2NetFly:
Ну и в шаблоне это дело удобно использовать:

[% News::List("tmp_1", LimitForm => 0, LimitTo => 3, OrderBy => ‘date’, OrderType => ‘DESC’) %] [% News::List("tmp_2", LimitForm => 3, LimitTo => 10) %]

:) Или на статические вызовы методов в шаблонах ты смотришь иначе ?

3. Да я с таким тоже сталкивался и как правило все делал через Ж...
Славу богу таких случаев было не так много.
Вообще я считаю что такой фреймворк должен упрощать разработку простых скриптов и хотя бы не усложнять разработку сложных вещей. И я не вижу ничего плохого в том, чтобы иногда отказываться от ORM, когда связей слишком много и они затрудняют работу.

Что касается твоего примера, то у меня давно крутится в голове идея, но до реализации пока так и не дошло. Суть примерно такая.
Пишем класс - назовем его SQLLoader. Назначение - он получает SQL-запрос, список пустых объектов (может быть список классов, но интуитивно объекты мне нравятся больше), выполняет этот запрос и возвращает объекты. Покажу на примере :

$a_list = new AuthorList(); // список авторов
$c_list = new CommentList(); // список комментов
$loader = new SQLLoader();
$loader->setSQL("SELECT a.*, c.* FROM authors a, comments c WHERE c.author_id = a.author_id AND c.article_id = 12");
$loader->setObjects($a_list, $c_list);
l$loader->load();
дальше в зависимости от реализации  (например если объекты были переданы по ссылке)  их можно уже использовать

Пока вижу здесь 2 проблемы
 - обеспечить ссылки между связаными объектами (именно это я пока не продумал)
 - неудобно работать, если в связанных таблицах  будут поля с одинаковыми именами полей

Кстати, в таком случае ИМХО есть преимущества в том, что "объект" и "список объектов" - это 2 разных класса.

$author = new Author(); // один автор
$comment = new Comment(); // один коммен
$loader = new SQLLoader();
$loader->setSQL("SELECT a.*, c.* FROM authors a, comments c WHERE c.author_id = a.author_id AND c.article_id = 12");
$loader->setObjects($a_list, $c_list);
while (l$loader->load()) {
   ....// здесь используем объекты $author и $comment
    ....// на каждой новой итерации они будут иметь новые значения
    .... /// в этом случае и со ссылками проблем не будет
}

Но это все вымышленный код, пока нет времени (да и потребности) реализовывать его.
Название: CMF на перле
Отправлено: 2NetFly от 10 Марта 2005, 20:54:10
Цитировать
Или на статические вызовы методов в шаблонах ты смотришь иначе?

У этих статических методов иное назначение, без них обойтись нельзя. Я имел в виду объекты как сущность (новость, комментарии и т.д.).

Касательно объектов и коллекций объектов в представлении - я наконец-то вспомнил, почему в свое время от них отказался. Представь себе, что тебе нужно вывести список 100 пользователей с подробной информацией о каждом (допустим, 10 полей). Тебе во-первых придется создать коллекцию из 100 объектов Пользователь, а во-вторых сделать тысячу вызовов методов! Я не думаю, что это будет очень быстро =) По крайней мере обход структуры займет в тысячи раз меньше времени. Поэтому я все больше и больше склоняюсь к мнению, что дополнительный слой нужен и он не должен быть связан с доменными классами.
Название: CMF на перле
Отправлено: Макс от 10 Марта 2005, 23:48:07
Цитировать
2NetFly:
 Касательно объектов и коллекций объектов в представлении - я наконец-то вспомнил, почему в свое время от них отказался. Представь себе, что тебе нужно вывести список 100 пользователей с подробной информацией о каждом (допустим, 10 полей). Тебе во-первых придется создать коллекцию из 100 объектов Пользователь, а во-вторых сделать тысячу вызовов методов! Я не думаю, что это будет очень быстро =) По крайней мере обход структуры займет в тысячи раз меньше времени.

1. Поскольку в большинстве случаев такие коллекции исползуются в скрипте всего один раз и почти всегда это обход коллекции в одну сторону, то не проблема реализовать их, незагружая сразу в массив (типа Lazy Load), а работая с одним объектом из коллекции.

2. такие массивы данных (как ты описал) обычно выводятся только в админках. А там вполне можно пожертвовать производительностью.

3. Всегда есть куча способов оптимизировать скрипт (компиляция шаблонов, кеширование, статика, акселераторы и т.п.) Так что это не проблема.
Название: CMF на перле
Отправлено: 2NetFly от 11 Марта 2005, 00:22:15
1. Не совсем понял, что имеется в виду.
2. При разработке mp3 архива подобные запросы мне приходилось выводить довольно часто: список исполнителей на определенную букву, лейблов, дат выхода альбомов и т.д.
3. Я бы сказал, что всегда есть куча способов усложнить программу =) В данном случае статика и прочее - это лишь усложнение, цель которого решить проблемы, которые решаются другими более простыми способами.

И все равно мне кажется, что объектам модели в преставлении не место. Доменными объектами можно (и нужно) манипулировать в классах-обработчиках, а представление (по определению) должно манипулировать данными, а не методами доменных объектов. Процитирую одного из участников дискуссии на форуме phpclub, мнение которого я полностью разделяю: "Собственно, зачем нам необходимо полностью загружать доменные объекты, если всего лишь требуется отобразить некоторую информацию во View?".
Название: CMF на перле
Отправлено: Макс от 11 Марта 2005, 12:13:44
Цитировать
2NetFly:
1. Не совсем понял, что имеется в виду.

Обычно список сущностей нужно просто получить из базы и вывести на странице. Поэтому даже если используются коллекции объектов, не надо сразу загружать все данные коллекции.
Задача класса DBObjectList не в том, чтобы сразу загрузить в объект все данные (это можно делать, а можно не делать - по желанию разработчика), а в том, чтобы стандартизировать работу со списками:

$list = new NewsList();
$list->getNewsForCategory($category_id);
if (!$list->empty) {
    while ($news = &$list->get()) {
       /// работаем с одной новостью
    }
}


Насчет представления - не считаю этот вопрос принципиальным.
Я не делаю никаких ограничений на представление - все на совести разработчика.
Название: CMF на перле
Отправлено: Макс от 11 Марта 2005, 12:17:24
Цитировать
2NetFly:
манипулировать в классах-обработчиках

вообще про отдельные классы-обработчики я еще подумаю на досуге.
Идея хорошая.
Название: CMF на перле
Отправлено: 2NetFly от 11 Марта 2005, 13:33:50
Я раньше использовал в качестве обработчиков методы классов (например, класс News метод add), но потом перешел на отдельные классы-обработчики. Преимуществ довольно много, основное из которых - возможность построения иерархии обработчиков и повторное использование кода. Т.е. создаешь common обработчики для добавления, удаления, модификации, а затем лишь указываешь на нужный доменный объект, с которыми они будут работать.
Название: CMF на перле
Отправлено: 2NetFly от 15 Марта 2005, 11:24:07
Приобрел неплохую книгу по паттернам в J2EE. Перевод ужасный, но довольно информативно. Прокомментировал несколько паттернов на блоге. Так же связался с разработчиками LIMB, они придумали очень интересный механизм организации команд в конечный автомат.