как грамотно спроектировать вызов статичных методов наследуемого класса

bkonst

.. хочется странного?...
[phprus]
Я все-же не понимаю чем в данном случае исключения хуже замыканий?
[/phprus]
В данном случае - ничем. И ничем не лучше, в общем-то.

Помоему решение с исключениями будет лучше, так как с большой вероятностью в $form->show_error() надо будет передать информацию о том, что же произошло. Помоему если использовать исключения то это можно будет сделать проще.
Учитывая, что в PHP нормальных замыканий нет - да. В том же Javascript - разницы нет. E.g.:
Код:
function foo() {
  ...
  account.withdraw(value, function() { form.show_success(); }, function(e) { form.show_error(e); })
  ...
}
Пока особой разницы нет, правда? Теперь предположим, что эта функция может вызываться в разных контекстах и должна в зависимости от контекста иметь разную реакцию на ошибки (например - выводить информацию на экран; сохранять в лог; вызывать милицию). При использовании closures передаем в foo соответствующие closures и имеет соответствующее поведение.
Без closures то же поведение можно имитировать, но код будет заметно более громоздким.

Аналогично, c closures может проще и нагляднее выглядеть обработка коллекций:
Код:
bonus = $$$;
listOfAccountsSubjectToBonus.each(function(account) { 
  account.deposit(bonus);
});
Автор оригинала: dark-demon
bkonst, ничего подобного. мы спрашиваем отработала ли функция полностью "или прочее". и тут не важно есть ли подозрения на жульничество и тп.
Еще раз говорю - бизнес-логика имеет мерзкое свойство меняться. На ходу. В последний момент.
И то, что легко можно добавить "подозрения на жульничество" - очень приятный плюс.
И то, что при желании куски обработки разных исходов можно хранить в одном месте - тоже плюс. Да, можно развести кучку маленьких классиков, используя паттерн Strategy. Можно обойтись closures.

это говорит не в его пользу. банальный пример: в большом куске кода у нас есть маленькая функция. и (о боже!) мы забыли проинициализировать переменную. в случае php - да ну и пофиг - переменная будет проинициализирован стандартным дефолтным значением и при попытке чтения будет выдан нотис. в случае замыкающихся языков - получите рандомный мусор в переменной без каких-либо предупреждений.
Откуда дровишки? Только не говорите, что вы пробовали.
 

phprus

Moderator
Команда форума
Crazy
Так что все строится опять же на раскрытии состояния объекта, но здесь мы не спрашиваем, каково оно, а делаем предположение.
В упор не виду раскрытия состояния объекта. Каким образом исключение раскрывает состояние объекта? Помоему следуя вашей логике вообще любая проверка на ошибки будет нарушение инкапсуляции ибо само сообщение об ошибке уже говорит что с объектом чтото не то.

Исключения полезны для другого: не сообщать, что на счету денег нет, а давать реакцию на действительно аномальные ситуации: попытка снять -10 рублей, потеряна связь с банком, не удалость стартовать транзакцию.
А с каких пор отсутствие денег на счету это не аномальная ситуация особенно для магазина?


P.S.
А почему мы вообще говорим что надо снять деньги аккаунту, а не кошельку пользователя? Помоему тут надо реализовать еще один класс кошелек и именно ему передавать такого рода команды. А account должен содержать в себе объект кошелек и предоставлять возможность доступа к этому объекту.
 

whirlwind

TDD infected, paranoid
Crazy честно пытался понять, чем Ваш пример отличается от тернарного кроме синтаксиса? Лично я не вижу смысл называть нечто замыканием, если оно не используется для объединения двух удаленных программных контекстов. ИМХО, без анонимных классов/методов/функций это не замыкание, а лишний геморой.
 

phprus

Moderator
Команда форума
bkonst
function foo() {
...
account.withdraw(value, function() { form.show_success(); }, function(e) { form.show_error(e); })
...
}

Пока особой разницы нет, правда?
А теперь предположим, что у нас поменялась бизнес-логика и нам надо обрабатывать 3 состояния: Все нормально, нет денег, мошенничество.
Тогда нам нужно будет всего лишь дописать еще один обработчик исключения ( лучше сделать иерархию исключений и в каждом блоке обработки ошибок перехватывать самый общий класс и в обработке этой ошибки громко ругаться на нештатную ситуацию, тогда будет сложнее забыть дописать обработку еще одного исключения. так как при тестировании код будет громко ругаться)
При использовании замыканий нам надо будет добавить в функцию account.withdraw еще один параметр и переписать все ее вызовы или нам придется изменить второй параметр чтобы ф-я принимала список (хеш-массив) функций обработки ошибок и опять же придется переписать все имеющиеся вызовы.

Теперь предположим, что эта функция может вызываться в разных контекстах
Разные контексты находятся в разных блоках кода следовательно можно написать разный код обработки исключений. Так что я всеравно не вижу более громоздкий код:
но код будет заметно более громоздким.
P.S. Скажите пожалуйста, что можно почитать про замыкания и про их преимущества на русском, а то мне эта тема не очень знакома.

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

Crazy

Developer
Автор оригинала: whirlwind
Crazy честно пытался понять, чем Ваш пример отличается от тернарного кроме синтаксиса? Лично я не вижу смысл называть нечто замыканием, если оно не используется для объединения двух удаленных программных контекстов.
Вернемся еще раз к моему коду:

Код:
$account.withdraw: $value success: [ $form->show_success(); ] error: [ $form->show_error(); ]
Один из двух блоков кода будет вызван из метода Account.withdraw. В контексте которого нет никакой переменной $form.

Переменная $form доступна в точке вызова.

Так что это замыкание в чистом виде. Именно что объединение двух различных программных контекстов.

-~{}~ 15.06.07 13:35:

Автор оригинала: phprus
Crazy
В упор не виду раскрытия состояния объекта. Каким образом исключение раскрывает состояние объекта?
Я вроде как уже написал парой сообщений выше: речь идет о конкретной ошибке "недостаточно денег". Там же я перечислил примеры исключений, которые не раскрывают состояние объекта.

А с каких пор отсутствие денег на счету это не аномальная ситуация особенно для магазина?
А с каких пор это аномальная ситуация? Код, запускаемый в случае недостатка денег, может отвечать за предоставление кредита. Вполне штатная операция.

А почему мы вообще говорим что надо снять деньги аккаунту, а не кошельку пользователя?
Это бессмысленный вопрос. Я нигде не описывал точный список ответственности класса Account. Кроме того, я вообще не вижу, какое это имеет отношение к обсуждаемой теме. :)
 

whirlwind

TDD infected, paranoid
> их преимущества на русском

Анонимные неймспейсы, которые позволяют не плодить сущности преждевременно и которые в последствии очень легко рефакторятся. Замыкания имеют смысл там, где кода мало. Например прототип show_error вызываемый из withdraw не совпадает с form::show_error - вместо того, что бы создавать новый класс "где то там" создается анонимный адаптор "прям здесь".

-~{}~ 15.06.07 13:40:

> Так что это замыкание в чистом виде.

Теперь понял. Просто форма записи непривычная.
 

phprus

Moderator
Команда форума
Crazy
Там же я перечислил примеры исключений, которые не раскрывают состояние объекта.
Вы имейте ввиду вот это:
Исключения полезны для другого: не сообщать, что на счету денег нет, а давать реакцию на действительно аномальные ситуации: попытка снять -10 рублей, потеряна связь с банком, не удалость стартовать транзакцию.
? Если да, то при первом прочтении я не обратил внимание на список конкретных аномальных ситуаций.

А с каких пор это аномальная ситуация? Код, запускаемый в случае недостатка денег, может отвечать за предоставление кредита. Вполне штатная операция.
Вот это ИМХО спорно. Я бы считал это аномальной ситуацией, а вот выдача кредита - это можно рассматривать как подсказка по ее разрешению в методе отображения ошибки. Я думаю в реальности не всем понравится если вместо сообщения о недостатке денег на их счету им без их согласия будет выдан кредит.

Это бессмысленный вопрос. Я нигде не описывал точный список ответственности класса Account. Кроме того, я вообще не вижу, какое это имеет отношение к обсуждаемой теме.
Да. вы правы. Это не имеет никакого отношения к теме, просто мне попалась на глаза моя виза, вот и возникла у меня мысль, что чтото не то с названиями объектов, а про то что это не имеет отношения к теме я както не подумал.
 

bkonst

.. хочется странного?...
Автор оригинала: phprus
bkonst

А теперь предположим, что у нас поменялась бизнес-логика и нам надо обрабатывать 3 состояния: Все нормально, нет денег, мошенничество.
...
Уели ;) Правильно, при изменении количества исходов с таким кодом преимущества не будет (разве что изначально вынести обработчики в ассоциативный массив или объект-стратегию). Однако, если изначально закладываться на то, что будут изменения - будет уже другая ситуация.

Разные контексты находятся в разных блоках кода следовательно можно написать разный код обработки исключений. Так что я всеравно не вижу более громоздкий код:
В этом случае мы не сможем продолжить выполнение код далее, так как исключение будет обработано в вызывающей функции.
Очень грубый пример этого:
Код:
function foo(onSuccess, onError) {
  ...
  account.withdraw(value, onSuccess, onError)
  ... делаем что-то еще ...
}

foo(function() { celebrate(); }, function(e) { silentlyLog(e); recover(); });
foo(function() { greetUser(); }, function(e) { loudShout(e); throw(e); });
В этом случае при первом вызове foo получаем, что при ошибке выполнение функции продолжится (скажем, внутри recover() "добавили кредит"), а во втором - нет. С помощью различных обработчиков исключений такое сделать будет нельзя.

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

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

dark-demon

d(^-^)b
Друг мой, ты сказал чушь. Доказывать тебе, что это чушь -- лично мне совершенно незачем.
друг мой, дорогой, это ты сказал чушь. и чтобы доказать, что это не так - изволь аргументировать свою позицию.

Когда ты его аргументируешь примерами кода -- будем разговаривать с тобой дальше. А пока -- свободен.
ещё один мультиакк фаната?

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

Откуда дровишки? Только не говорите, что вы пробовали.
а что, прям такая невероятная ситуация?
 

bkonst

.. хочется странного?...
Автор оригинала: dark-demon
добавляй. я не против. только не надо функциональность аккаунта разбрасывать по всей программе. ну вот ты сделал с помощью коллбэков отправку мыла админу в случае подозрений. админа это задолбало. теперь надо, чтобы эта инфа заносилась в реестр и операция блокировалась - снова побежишь исправлять все коллбэки?
Это не функциональность аккаунта.

а что, прям такая невероятная ситуация?
Я так и понял. Как обычно, несет чушь тот, кто не пробовал.
 

dark-demon

d(^-^)b
ты об этом?
Аспектно-ориентированное программирование (АОП) — парадигма программирования, основанная на идее разделения функциональности, особенно сквозной функциональности, для улучшения разбиения программы на модули.
^_^
 

dark-demon

d(^-^)b
ну так весь аоп как раз и построен на том, чтобы выделять свозную функциональность в отдельные сущности, а не разбрасываться ею по разным объектам.
 

bkonst

.. хочется странного?...
Ну и как это
ну так весь аоп как раз и построен на том, чтобы выделять свозную функциональность в отдельные сущности, а не разбрасываться ею по разным объектам.
сходится с этим:
Это не функциональность аккаунта.
а чья же?
 

dark-demon

d(^-^)b
а сходится так, что не любую функциональность есть смысл выделять в отдельные сущности. обсуждаемая функциональность в контексте рассматриваемой проблемы относится к аккаунту. вот если у нас появятся (или есть предположение, что они могу появиться) другие объекты с аналогичной функциональностью, тогда и следует оную выделять в отдельную сущность.
 

bkonst

.. хочется странного?...
То, что функциональность можно запихнуть в класс аккаунта, еще не значит, что она относится к этой сущности.
 
Сверху