Открыть список
Как стать автором
Обновить

Комментарии 62

все замечательно, единственное я бы заменил
echo $user->getBlog()->getTopics()->topic[$topic_id]->message;
на
echo $user->getBlog()->getTopic($topic_id)->message;
дабы не создавать класс, представляющий из себя массив топиков.
да и разруливать ситуацию, когда запрашивается отсутствующий топик так гораздо проще.
а в целом объекты — наше все.
когда-то хотел было сделать именно так, но сама коллекция топиков может иметь методы. например ->clearAll()
коллекция топиков чересчур абстрактная сущность. $blog->clearAllTopics() — значительно более прозрачное действие удаления всех топиков блога (хотябы явно видно что удаляються топики конкретного блога).
ну и соответственно $user->clearAllTopics();
по крайней мере я всегда делаю так, но было бы интересно подискутировать на эту тему).
Я думаю автор хотел донести общую идею, а не предложить реализацию какой-то конкретной задачи.
да, вы правы. просто для меня эта тема актуальна и интересна, вот я и поинтересовался его мнением по этому конкретному случаю.
ммммм.... $blog->clearAllTopics() - вкусный пример :), но вот с $user->clearAllTopics() поспешу не согласиться. Не соглашусь по причине излишней связанности классов. Как итог будем иметь проблемы расширяемости приложения, а так же не совсем четкую логику - снова возвращемся к неймспейсам :)
Сохраняя иерархию объектов, получаем более логичную структуру
в чем то вы правы.
Однако при увеличении количества блогов и топиков операция удаления всех топиков пользователя происходила бы путем перебора всех блогов юзера и последовательным вызовом $blog->clearAllTopics();
Притом возможность работы напрямую со всеми топиками юзера непременно может понадобиться (например для создания rss ленты юзера), и тогда удобно будет использовать $user->getAllTopics() ну или в дальнейшем $user->getAllComments();

В любом случае связь между объектами Blog, User и Topics очень тесная и совсем отделить их друг от друга не получиться (да и нужно ли?).
не получиться только контексте приложения, которое я описал, а если наша система завязана не только на блоги, но и на многие другие аспекты жизнедеятельности пользователя на портале? Ссылаться на специфические функции отдельных элементов системы из объекта пользователя - это уже некоторый перебор по-моему
За создание rss ленты пользователя должен отвечать метод пользователя: $user->getBlogsAllRSS() & $user->getBlogRSS(), а за список топиков блога — метод блога.
Увеличение изоляции избавляет от головных болей.
извините, поторопился :)
$user->getRSSBlogsAll() & $user->getRSSBlog()
А мне мерещится что-то типа
$rss->findByUser($user->getId());
$rss->findByBlog($blog->getId());
и
$posts->findByBlog($blog->getId());
коль уж сущности очевидны, то и быть им реализованными в отдельных классах
С первыми согласен, сущность отдельная, а вот посты сущность внутренняя для блога, не стал бы разделять.
А кто говорит, что они только к блогам могут относиться? ;)
дык конкретный пример рассматриваем, так ведь можно скатиться к общим интерфейсам списков и слова Blog и Comments потеряют здешний смысл :)

$rss->get( SomeArrayList list, Hashtable fields );
"Внутренняя" — это инкапсулированная коллекция постов внутри блога? Или всё же связанная?
Я имел в виду инкапсулированную коллекцию объктов.
Думаю сущность rss не должна включать сущности других объектов, дабы мы никогда не знаем сколько етих сущностей будет в будущем.
Скорее сущность rss должна описывать какие-то базовые действия для генерации rss и инкапсулироваться :)

$user->getBlogs()->getRss();

:)
Чем rss отличается от обычной html ленты постов? По-моему, только способом представления данных, т.е. шаблоном. Получается что для отдельного вида шаблонов (RSS) мы создаем новую сущность (объект, класс) и тем самым плодим их (сущности).
На мой взлад для создания rss ленты нам нужно две вещи: массив данных и xml-шаблон для их вывода. Зачем объекту юзер думать о том, в каком виде (шаблоне) его данные будут выводиться, зачем ему вообще о шаблонах знать что-то?

Другое дело что подготовка массива данных для вывода в xml-шаблоне довольно рутинная операция: нужно привести массив к определенному стандартному виду (например к полям типа title, description, date, url и т.д.). И для этого возможно понадобиться класс, который эту рутину будет максимально просто выполнять. Для примера можно посмотреть Zend_Feed, который именно этим и занимается.

А добавлять логику работы с rss в $user или $blog и прочие объекты, на мой взгляд, не стоит.
имхо разумеется)
а может описать это паттерном Стратегия? :)
да. это уже способ реализации. я думаю что в данном конкретном случае Strategy, а значит и классы-реализации стратегии излишни. хотя все зависит от обстоятельств конечно. кстати, раз речь о патернах: как можно назвать патерн, который реализует Zend_Feed? Декоратор, агрегатор... не силен в теории.
Да как угодно описать можно, но сути это не меняет: юзеры — это юзеры, а посты — это посты. И последние можно (да и нужно будет) не только в контексте пользователя выбирать. Лучше уж отдельно их.
А низ-зя, так как нам ясно сказали, что это коллекция, инкапсулированная в блог. Сослаться на все комменты юзера к постам во всех блогах — это непонятно решаемая задача в этой архитектуре.
и вам тоже "да-да-да" )
Где тут табличка "Аплодисменты" :)
Пример хорошо показывает, что при программировании надо пользоваться естественным языком.

Многие сразу садятся на за написание кода, а для начала следовало бы обдумать все сущности и действия над ними, а это нормальный человек делает на своём родном языке. Потому и код потом читается по-людски, а не по-писишному :)
Это всё конечно прекрасно. До того момента когда во время проекта приходится пересматривать сущности.
Я думаю, что "пересмотром" кода надо занимать в конце проекта. Т.е. рефакторингом кода.
Да, согласен, основную архитектуру надо продумать сразу и описать сразу, но сущности... могу поспорить в большом проекте они будут пересматриваться не один раз и не два. Вот тогда можно и запутаться в сущностях (что откуда и куда).
Вот когда проект подошел к beta тогда и можно рефакторить и переводить в сущности и т.п. чтобы в будущем было уже легко денормализировать и масштабировать проект.
А зачем сделаны открытыми атрибуты блога? Вы собираетесь их менять извне?
собственно пример :) насчет методов доступа могу закросспостить еще статью из своего блога, если интересно...
засылай, интересно
1. Никогда не понимал чепухи про то, что "время жизни скрипта PHP намного меньше". Меньше чего? Меньше для кого? С точки зрения человека? Причем тут человек? Для процессора время жизни скрипта - миллиарды тактов, за это время можно много чего успеть.

Видимо, этими словами пытаются выразить другой аспект - PHP-сценарий не интерактивен. В процессе выполнения, ему не нужно реагировать на действия пользователя. Но тут он ничем не отличается от других неинтерактивных процессов, пусть они хоть неделями крутятся.

Если понять основную задачу PHP - формирование ответа на основании запроса - и не пытаться эмулировать интерактивность, то оказывается, что ООП в PHP ничем в принципе не отличается от ООП в других областях.

2. По моему скромному ИМХУ, сравнение программных объектов и объектов окружающего мира, одна из самых вредных привычек программистской литературы. Сколько неподготовленных мозгов забито этой догмой, не пересчитать.
касательно первого - да, именно это и подразумевалось, но выразил суть таким образом, чтобы было понятно всем, а не только 10% читателей
касательно второго... нууу тут я позволю себе не согласиться. Тождестевнность подобного рода позволяет развить понимание ООП, как явления, а не просто пользоваться его техническими преимуществами на уровне языка программирования.

в дополнение. В данном топике я старался раскрыть лишь подход к реализации взаимодействий объектов, а не подменять понятия
IMHO тут имеется в виду сессионный характер работы скрипта, т.е. мы поднимаем мегабайт объектного кода для выдачи одной странички. Вот и возникают вопросы целесообразности.

Примеры реальных объектов приводятся для начинающих, которым проще оперировать, тем, что можно пощупать. Но одно из главных преимуществ ООП в возможности моделирования абстрактных объектов, а к ним надо переходить после практики с реальными, так просто проще большинству.
Так не надо мегабайты. На ООП можно и компактно писать. Опять таки здесь весьма субъективная мера. "Для выдачи одной странички" - почему к страничке нужно относиться пренебрежительно?


Примеры реальных объектов приводятся для начинающих, которым проще оперировать, тем, что можно пощупать

Да, и эти примеры хороши на первых двух страницах объяснения. А дальше это уже больше похоже на беспомощность автора в объяснении сути ООП.
Есть ведь еще и сторонние библиотеки и комментарии нельзя хранить отдельно. И 840к кода текущего проекта мной написано только 200 (шаблоны, конечно, не в счет).
IMHO компактный код — признак недостаточного абстрагирования, на других проектах придется перетачивать.

>почему к страничке нужно относиться пренебрежительно?
Потому что большинство из них достаточно тупые, которые не требуют мощного аппарата.

От автора зависит :) Бадд в "ООП" тоже начинает с объктов реального мира (цветочница, покупатели, товар и прочее), потом ничего так :) для введения.
Абстракция не эквивалент ООП. Можно и без ООП абстрактно писать, можно и с ООП не впадать в излишние крайности.
Да, конечно, но с ООП это делать значительно проще. Зачем прикладнику себя мучать?
> IMHO компактный код — признак недостаточного абстрагирования, на других проектах придется перетачивать.

Смысл абстрагирования — в написании мегабайтов кода?
Смысл в наименьших усилиях, прилагаемых программистом, при изменении начальных условий или при старте нового проекта.
Надо каждый проект начинать с полного конструирования?
Но это все надо понимать без фанатизма, сам не люблю мегамонстров.
У меня есть своя абстрактная библиотека и куча реюзабельных классов под неё. В частности, сейчас на http://nav.academ.org/freedom/ кода под, собственно, проект — 22 килобайта. Скорость генерации страниц — от двух до пяти миллисекунд.

И код при этом достаточно компактен.
эти 22 кб делают всё всё?
В рамках данного проекта — да. Ещё раз повторю, что ни библиотеку, ни классы, которые реюзаются, я не считаю.
Т.е. ты так и сделал: написал мегабайты абстракций и уложил всю работу с ними в 22кб, почему ты тогда на меня нападаешь :)
Это спор ни о чем, сам перечитай:

>кода под, собственно, проект — 22 килобайта
и
>что ни библиотеку, ни классы, которые реюзаются, я не считаю

ну а для одного списка и поиска по нему, наверное даже много, админка наверное съела.
Спора нет. Разве что с моей стороны. Есть дискуссия.

Код вполне абстрактный, но компактный.
Что касается объёма — не много. Четыре вьюшки, контроллер, три модели. Если на 22 разделить на 8, получается меньше трёх килобайт на класс (включая комментарии).
жаль что не качается...
али там только для своих?
Если про анимки — да, они доступны из новосибирских локальных сетей.
что есть несомненно плюсом - это Вы о чем? :-)
о том что чем больше кода, не требующего комментариев, тем лучше :)
С одной стороны про статический вариант Вы пишите "имеет массу плюсов", с другой стороны "давайте опишем очки". Где вывод?

Почему роль пользователя неочевидна для этой строки кода

Blog::addTopic($userId, $topic_message);


и почему она проясняется в этой строке

new User($user_id)->getBlog()->addTopic($topic_message);


и почему

Blog::getMessage($messageId);


хуже

new User($_SESSION['user_id'])->getBlog()->getTopics()->topic[$topic_id]->message;
"масса плюсов" еще не означает "неоспоримое преимущество" - не надо в крайности впадать :)

насчет недостатков и преимуществ:
1) семантика
2) логичность поведения участка кода (собственно то о чем вся статья)

насчет последнего:
Blog::getMessage($messageId); - вообще не ясно откуда взялся и что из себя представляет. Что за абстрактный блог? Просто запись в БД? Тогда еще прозрачнее написать:
SELECT * FROM blog WHERE id = $messageId


я не претендую на единственность решения и реализация. Я лишь хочу показать какой подход более логичен, а какой более непредсказуем
>> Blog::getMessage($messageId); - вообще не ясно откуда взялся и что из себя
>> представляет. Что за абстрактный блог?

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

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

Воспринимайте статью как рекомендацию. Считаете её правильной - возьмите на вооружение. Нет - так и скажите, аргументируя. Но зачем доказывать, что ямб лучше хорея :)
Автор как бы говорит нам — ООП принципиально хорошо? ) Дык тогда тут сейчас холивар вообще начнётся. Ау! Процедурно-функциональные адепты!?
Лучше уж всё-таки так, как сейчас, пообщаться. Оно так полезнее и нагляднее. Да и отвлечённых споров не провоцирует. В общем — в рамках заданной темы лучше холиварить, чем вообще херить тему отвлечёнными постами =) Упс.
Автору спасибо, что вот так вот запросто и просто поднял тему. Надеюсь, будет продолжать, усложнять, приводить примеры.
Усложнять не надо - пусть не отбивает желание читать посты :)
"Процедурно-функциональные адепты!?"

Вот ить! Ни одного такого не видел.
пока меня медленно но уверенно занижают в карме, так что не обещаю, что к вечеру вообще окажусь "разговорчивым" :)))
Это процедурно-функциональные адепты :)
Совмещаем "несовмещаемое"
ооо!


echo $user->getBlog()->getTopics()->topic[$topic_id]->message;

ИМХО вместо message надо, getMessage()! Зачем давать доступ к свойствам напрямую????
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.