McLotos
11.06.2019 - 11:13
Всем привет =)
У меня немного рвёт шаблон, он прям трещит по швам.
Вот смотрите есть паттерн Decorator, его суть предельно проста - есть классы, у которых нужно нарастить функционал, не трогая сами классы. Пишем decorator, вызываем в нем декорируемый объект и дальше делаем всё что хотим, например прикручиваем логгер или систему уведомлений, обработчики событий. Я логично подразумевал что интерфейс декоратора должен быть таким же как и у класса, который он декорирует, чтобы можно было если что выкинуть декоратор и использовать чистую реализацию.
И есть паттерн Proxy, который перехватывает запросы к оригинальному объекту и может выполнять какие-то действия до и после вызова реального метода основного объекта. Например логгер, который логирует Request до того как отдать его в класс и логирует ответ до того как выдать его в Response
Логично что для безболезненного внедрения, его интерфейс тоже должен совпадать с интерфейсом проксируемого класса.
Где я тут ошибся? Что у меня не то в логике? Если они одинаковые, то почему называются по-разному? Тот редчайший случай, когда refactoring.guru не внёс ясности в этот вопрос, скорее наоборот =(
_____________
программирование - инструмент для решения конкретных задач, любая попытка спроектировать что-то универсальное приведет к провалу.©paul85
В любом случае тебе прийдётся пройти путь изобретения велосипеда, который прошли другие, только причиной твоего изобретения будет непонимание принципов работы велосипеда изобретённого другими людьми.©SlavaFr
jQuery это попытка использовать АН-225 для перевозки зубочистки
Декоратор изменяет функционал, прокси дополняет. Вот и вся разница.
_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.
McLotos
11.06.2019 - 11:45
Ну вот например если мне нужно чтобы ответ контроллера был возвращен в json или в xml, в зависимости от header-а запроса, тут применять decorator? а если мне нужно просто добавить логирование, то тут применять proxy?
Получается что к одному классу User extends Controller нужен еще UserDecorator, который применит стратегию JsonResponse или XMLResponse, и нужен еще UserProxy, который будет логировать всё происходящее? Почему-то каждый раз, когда появляется очередной паттерн, количество кода только увеличивается, а ведь раньше просто обходились одним index.php
_____________
программирование - инструмент для решения конкретных задач, любая попытка спроектировать что-то универсальное приведет к провалу.©paul85В любом случае тебе прийдётся пройти путь изобретения велосипеда, который прошли другие, только причиной твоего изобретения будет непонимание принципов работы велосипеда изобретённого другими людьми.©SlavaFr
jQuery это попытка использовать АН-225 для перевозки зубочистки
Декоратор
изменяет методы. Прокси обычно добавляет другие, оставляя нетронутыми методы исходного класса. Хотя это все так размазано,как и все махровое ООП. )))
Кстати, чем больше проходит времени, тем чаще
слышится анафема для ООП от опытных, наевшихся этого д... программистов)))
_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.
McLotos
11.06.2019 - 12:57
Ну мы все тут знаем как ты не любишь ООП =)
Так в итоге мне что делать? Сделать проксю, которая будет вызывать декоратор а он уже будет стучаться к самому контроллеру? Ну это на случай если я хочу к контроллеру добавить логирование и преобразовывать его ответы в json =)
_____________
программирование - инструмент для решения конкретных задач, любая попытка спроектировать что-то универсальное приведет к провалу.©paul85
В любом случае тебе прийдётся пройти путь изобретения велосипеда, который прошли другие, только причиной твоего изобретения будет непонимание принципов работы велосипеда изобретённого другими людьми.©SlavaFr
jQuery это попытка использовать АН-225 для перевозки зубочистки
Сделай как тебе удобно и обзови хоть горшком. Че так все в эти паттерны уперлись, они же не догма. Получится прокси-декоратор и слава яйцам.
_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.
McLotos
12.06.2019 - 07:23
Ну собственно мы опять пришли к твоему классическому ответу. twin, ты классный специалист, но твоя нелюбовь к паттернам иногда реально мешает =)
вопрос изначально был не столько в практическом использовании, сколько для понимания ситуации в целом. Вот лично для меня decorator и proxy выглядят одинаковыми, и мне хочется разобраться в чем же они разные и как их вместе использовать. Может я не буду использовать их реально на практике, но понимать их не мешало бы, хотя бы для того чтобы не плеваться когда наткнусь на код очередного бездумного фаната паттернов
_____________
программирование - инструмент для решения конкретных задач, любая попытка спроектировать что-то универсальное приведет к провалу.©paul85
В любом случае тебе прийдётся пройти путь изобретения велосипеда, который прошли другие, только причиной твоего изобретения будет непонимание принципов работы велосипеда изобретённого другими людьми.©SlavaFr
jQuery это попытка использовать АН-225 для перевозки зубочистки
С чего ты взял, что я не люблю паттерны?)))
Это как в анекдоте про грузина.
- Ты памыдоры любищь?
- Кущать любблю, а так - НЭТ!
Как можно их любить или нет... Это же просто паттерны. Я противник того, чтобы все стараться делать на них, потому что это нименуемо ведет к проблемам ООП. Которые приходится разгребать всякими SOLID и иже с ним. НО это дело личное.
Что касается сабжа, я же сказал в чем отличие. Ну на вот кодом:
Вот это прокси:
class Proxy
{
public function getValue()
{
return (new MyClass)->getValue();
}
}
А это декоратор:
class Decorator
{
public function getValue()
{
$value = (new MyClass)->getValue();
return htmlspecialchars($value);
}
}
Их легко можно сложить в один класс и назвать прокси-декоратором. Или деко-прокси. Или горшок. Не важно, это условности. Важно, чтобы было удобно.
_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.
Эли4ка
12.06.2019 - 08:24
Цитата (McLotos @ 11.06.2019 - 10:45) |
Ну вот например если мне нужно чтобы ответ контроллера был возвращен в json или в xml, в зависимости от header-а запроса, тут применять decorator? а если мне нужно просто добавить логирование, то тут применять proxy? |
Мне тоже недавно понадобилось сделать аналогичное. Хочу задать вопрос-разве без прокси или декоратора это не осуществимо? Или сложнее поддерживать код? Или работает хуже?
Эли4каТут вопрос что первично, курица или яйцо. Если ты сделаешь что то аналогичное, это и будет прокси или декоратор. Другое дело, когда ты изучишь их теоретически, а потом начнёшь притыкать куда ни поподя только потому, что это паттерн и что он где то там описан в GoF..
Как сказал Фаулер, патерны обязательно нужно изучить для того, чтобы знать, где их применять не нужно.
Нужно писать не оглядываясь на патерны, а исходя из логики программы, её эффективности, поддерживаемосьи и прозрачности. А паттерн обычно провоцируют делать обратное, опрпадываясь высокими уровнями абстракция, которые по большому счету не просто бесполезны, но и зачастую вредны.
McLotos
12.06.2019 - 13:12
Цитата (Эли4ка @ 12.06.2019 - 10:24) |
Хочу задать вопрос-разве без прокси или декоратора это не осуществимо? Или сложнее поддерживать код? Или работает хуже? |
Осуществимо, если тебе хочется каждый раз править контроллеры, если завтра к json добавится xml. Будешь бегать по всем контроллерам и править? А так можно добавить еще один декоратор и всё будет работать
Цитата (Guest @ 12.06.2019 - 12:52) |
Как сказал Фаулер, патерны обязательно нужно изучить для того, чтобы знать, где их применять не нужно. |
Фаулер гений
Цитата (Guest @ 12.06.2019 - 12:52) |
Нужно писать не оглядываясь на патерны, а исходя из логики программы, её эффективности, поддерживаемосьи и прозрачности. |
Да, тут скорее логика должна быть наоборот. Для решения какой-то проблемы, можно найти паттерн, который поможет ее решить с минимальным затрахом (сорри, но по-другому не скажешь). А не наоборот - когда испольуют паттерны ради паттернов и получают еще больше головной боли. Вот тут я с Мартином согласен =)
_____________
программирование - инструмент для решения конкретных задач, любая попытка спроектировать что-то универсальное приведет к провалу.©paul85
В любом случае тебе прийдётся пройти путь изобретения велосипеда, который прошли другие, только причиной твоего изобретения будет непонимание принципов работы велосипеда изобретённого другими людьми.©SlavaFr
jQuery это попытка использовать АН-225 для перевозки зубочистки
Эли4ка
12.06.2019 - 17:22
Цитата (McLotos @ 12.06.2019 - 12:12) |
Осуществимо, если тебе хочется каждый раз править контроллеры, если завтра к json добавится xml. Будешь бегать по всем контроллерам и править? А так можно добавить еще один декоратор и всё будет работать |
Это как часто нужно менять структуру выдачи ответа в json чтобы ради этого делать декоратор?
Сделал json, xml ответы и забыл. Обновилось API - добавил новые поля.
json, xml это не те вещи, где нужно применять декоратор и уж тем более прокси.
Цитата (McLotos @ 12.06.2019 - 09:12) |
Осуществимо, если тебе хочется каждый раз править контроллеры, если завтра к json добавится xml. |
А если не добавится?
Что кстати скорее всего.
Так что прежде чем изучать паттерны, изучи антипаттерны. Фаулер не зря это изрек.
В твоем случае это похоже на "золотой
дождь молоток", а так же прямое нарушение YAGNI.
Ты сам уже заметил, что
Цитата (McLotos @ 11.06.2019 - 07:45) |
Почему-то каждый раз, когда появляется очередной паттерн, количество кода только увеличивается, |
Подумай хорошенько, сколько тебе потребуется времени, чтобы добавить новый формат и сколько вообще есть таких форматов. У тебя овер 1000100 контроллеров?
И с удивлением заметишь, что время, потраченное тобой в попытках применить универсальное решение, потому что ты где-то краем уха слышал про паттерны, намного превышает время таких правок.
Тем более что
1. Вероятность смены формата обычно стремится к нулю.
2. Какого хрена вообще выбором формата занимается контроллер?
Ты бы лучше подумал бы об архитектуре, а не пытался залатать дыры ООП костылями в виде этих паттернов, которые именно для латания дыр и придуманы.
Применять их нужно только тогда, когда дыра реально и неизбежно уже нарисовалась, но никак не заранее. Ты все равно все не предусмотришь, а код распухнет так, что вся полуторомиллиардная Индия заплачет от тоски и досады.
_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.
McLotos
Я их всех врапперами называю)
А разница у них как я понимаю только в теоретической части. Это как сказать "насыпь 100 грамм" или "налей сто грамм", оба варианта означают что надо из одной тары в другую переместить 100 грамм, но при этом уточняют более конкретно.
Задача прокси - перенаправлять запросы. Можно в прокси навешать логгеров и много чего ещё, но это не его основная задача.
Пример 1: есть библиотека у которой методы называются не в стиле твоего приложения, можно обернуть её в прокси и переименовать методы. будешь обращаться к $vasyaProxy->getViews() вместо $vasya->give_me_views_ёpte()
Пример 2: есть библиотека у которой скрыты свойства, а тебе они нужны, вместо того что бы каждый раз рефлексией смотреть в этот класс, ты пишешь эту логику один раз в прокси.
Пример 3: есть библиотека, которая делает добро, ты не хочешь что бы все подряд могли получить добро на халяву, делаешь прокси в котором проверяешь что за добром пришли с разрешённого ip.
Пример 4: есть библиотека, которая часто обновляется и автор постоянно методы переименовывает, меняет количество и места аргументов. Делаешь прокси со стабильным интерфейсом и горя не знаешь.
Пример 5: есть библиотека, ты хочешь палить кто там какой пароль вводит, делаешь прокси, проксируешь, тыришь данные, логгируешь это всё себе в заначку.
Пример 6: есть несколько библиотек, которые переводят тексты. Одна переводит с гугла, другая с яндекса, у каждой лимит, делаешь прокси который рандомно подключает библиотеки, тем самым балансирую между ними, удваивая лимит, утраивая лимит итд, всё через один интерфейс.
То есть в прокси ты не менял данные. Ты их украл, ты поменял интерфейсы, сделал балансировщик, но данные проксировал как есть.
У декоратора задача добавить новый функционал или поменять старый. Это такая же обёртка как прокси, но делает другие вещи.
Пример 1: есть библиотека, которая отправляет почту, тебе надо что бы матерные слова вырезались, делаешь декоратор, который вырезает мат из текста перед отправкой в библиотеку почты.
Пример 2: есть библиотека, которая загружает файлы и возвращает тип, размер, где лежат файл итд, но не возвращает хэш файла, делаешь декоратор.
Пример 3: есть библиотека, которая загружает файлы но не умеет их удалять, делаешь декоратор, в который добавляешь новый метод.
Пример 4: есть библиотека у который 100 методов, а тебе нужны только 5 и ты не хочешь что бы другими пользовались потому что они не нужны и ты их в доке даже не описывал. Делаешь декоратор, где только 5 методов.
То есть декоратор он почти как прокси, но может данные поменять, может добавить нового функционала, может порезать старый, может упростить/усложнить интерфейс.
Наверное можно мои пункты по други паттернам разложить, сериализеры, валидаторы итд. Я где то натыкался что декоратор это просто более высокий уровень абстракции чем прокси. Как враппер более абстрактный чем декоратор. Но я бы не стал называть декоратором то, у чего идея классического перенаправления данных, декоратор для меня это типа наследования, где ты можешь всю логику переделать, все данные перевернуть.
Пример с переводчиками, есть библиотека, которая возвращает данные, есть декоратор, который переводит через яндекс, есть другой, который переводит через гугл, и есть прокси, который балансирует декораторами. Вот так прокси->декоратор1/2 ->библиотека
_____________
Промокод предоставляет скидку на заказ домена и/или хостинга reg.ru
BFCC-3895-8804-9ED2
Давненько ничего не постил, так что всех приветствую! =)
Цитата (McLotos @ 11.06.2019 - 11:13) |
Где я тут ошибся? Что у меня не то в логике? |
Декторатор все же чаще всего подразумевает под собой матрешку, то есть совеобразные цепочки вызовов, внедренные через конструктор. Или можно сравнить с рекурсией особого вида. Применяется, например, для борьбы с комбинаторным взрывом в задачах компоновки.
"Единичный" дектоатор структурно ничем не отличается от прокси. Разница чисто формальная, на тему чего можно холиварить, если есть желание (читай нечего делать). Тут станет предельно понятно из контекста и нет смысла придираться. Например: "я сделал сортировку/фильтр данных через прокси" или "я сделал сортировку/фильтр данных через декоратор". Смысл по сути один и тот же, только во втором случае скорее всего на ум придет какая-то сложная сортировка многоэтапная, которая может зависеть (и скорее всего) от внешних факторов, допустим от UI. Тут важно другое. Тебя собеседник поймет и так и сяк, а значит цель достигнута. В конце концов не в названиях дело, тем более столь родственных по структуре паттернов.
Но все же, когда речь идет именно о прокси, подразумевают логирование, кэширование и т.д. то есть как способ внедрения вспомогательных инструментов. Декторатор, обычно, имеет куда более существенное отношение к бизнес-логике.
Цитата (McLotos @ 12.06.2019 - 13:12) |
Осуществимо, если тебе хочется каждый раз править контроллеры, если завтра к json добавится xml. |
В местах где вероятно появление ветвления, но пока его нет, достаточно просто объявить интерфейс. И YAGNI не будет нарушен в случае чего, и в будущем с расширением не будет проблем. Есть даже мнение, что интерфейсы нужно объявлять вообще всем классам, но я по правде не сторонник. Возможно сие стремление уходит корнями в С++, если понимаете о чем я.
Быстрый ответ:
Powered by dgreen
Здесь расположена полная версия этой страницы.