LINUX.ORG.RU

А существует ли стратегия?:)

 , ,


0

1

Вчера я начал разбираться, и будто бы, начал что-то понимать, (спасибо всем откликнувшимся, отдельное спасибо TDrive), но сегодня решил разобрать следующий пример, и снова впал в какой то ступор.

взято отсюда: http://habrahabr.ru/post/191480/

// Greeter - класс объектов, которые могут приветствовать людей.
// Он может выучить различные способы приветствия через стратегии
var Greeter = function(strategy) {
    this.strategy = strategy;
};
 
// Greeter содержит функцию greet,
// которая будет использоваться для приветствия людей
// через стратегии, переданные в конструктор
Greeter.prototype.greet = function() {
    return this.strategy();
};

// Так как функция инкапсулирует алгоритм,
// она отличный кандидат на роль стратегии

// Немного стратегий:
var politeGreetingStrategy = function() {
    console.log("Hello.");
};
 
var friendlyGreetingStrategy = function() {
    console.log("Hey!");
};
 
var boredGreetingStrategy = function() {
    console.log("sup.");
};
 
// Давайте используем их!
var politeGreeter = new Greeter(politeGreetingStrategy);
var friendlyGreeter = new Greeter(friendlyGreetingStrategy);
var boredGreeter = new Greeter(boredGreetingStrategy);
 

Код, воистину элементарен.

Все это можно переписать вот так

Greeter=function(strategy){this.strategy=strategy}
Greeter.prototype.greet=function(){this.strategy()}

politeGreeter=new Greeter(function(){console.log("Hello")})
friendlyGreeter=new Greeter(function(){console.log("Hey")})
boredGreeter=new Greeter(function(){console.log("sup")})
То есть, де факто, автор просто создает экземпляры Greeter, и сеттит им поведение. Иными словами, делает то, что мы и так всегда делаем, когда пишем ООП-код. Больше тут ничего нет.

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

Greeter=function(greeting){this.greeting=greeting}
Greeter.prototype.greet=function(){console.log(this.greeting)}

politeGreeter=new Greeter("Hello")
friendlyGreeter=new Greeter("Hey!")
boredGreeter=new Greeter("sup")
Ибо нефиг размазывать поведение по объектам, там где его можно обобщить.

А может нет никакой «стратегии», а? Может это фантом коллективного-бессознательного?

У тебя оверинжиниринг, будь проще:
console.log(«Hello»);
console.log(«Hey!»);
console.log(«sup»);

Перестань воспринимать примеры, которые ты используешь, как примеры того, как выполнить подряд 3 разных функции.

winlook38 ★★
()
Ответ на: комментарий от winlook38

хз, я считаю, если человек приводит какой-то пример, этот пример должен быть релевантен, в том смысле, что он должен ка-то показывать, что нам это дает. Должна быть какая то цель, абстракция должна быть связана с какой-то задачей. А если наша цель — просто вывести 3 слова на экран, то да, достаточно того, что ты написал. Мы же пишем ООП не ради того, чтобы код выглядел ООП, правда?

javaQest
() автор топика
Ответ на: комментарий от javaQest

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

winlook38 ★★
()
Ответ на: комментарий от winlook38

Вот и один из тамошних комментаторов, в некотором смысле со мной согласен

По-моему кое-чего не хватает в этой статье и в статье в википедие — примера в стиле «Было плохо — стало хорошо». Сразу получается «хорошо» и не достаточно ясно, что это действительно хорошо. Буду благодарен за такой пример.

javaQest
() автор топика
Ответ на: комментарий от loyd

Да, в принципе, там описано то же самое, что он прочитал по ссылке с примером на JS.

winlook38 ★★
()
Ответ на: комментарий от javaQest

И да, до кучи: забудь уже про with в коде и открой для себя ES6. ООП паттерны все-таки для классовой модели (хотя у той же банды четырёх есть примеры и на smalltalk). Ну а в контексте js, большая часть этих паттернов вообще теряет смысл (для typeclass-based ЯПов аля haskell или rust так вообще все).

loyd
()
Ответ на: комментарий от loyd

забудь уже про with в коде и открой для себя ES6

with есть в стандарте ES6, его никто не отменял

Ну а в контексте js, большая часть этих паттернов вообще теряет смысл

Почему? Вот, например, патерн Observer вполне юзабелен, я его часто пользую.

javaQest
() автор топика
Ответ на: комментарий от javaQest

with есть в стандарте ES6, его никто не отменял

with запрещён в strict-моде, а вообще это были два отдельных пункта (перестать использовать with и использовать «классы» из ES6, ибо паттерны).

Вот, например, патерн Observer вполне юзабелен, я его часто пользую.

большая часть

loyd
()
Ответ на: комментарий от javaQest

Ты лучше скажи, зачем он тебе сдался? Я тебя уверяю, когда он тебе понадобится, ты сам его придумаешь. Так со всеми шаблонами. Читаешь их описание и не понимаешь зачем все эти сложности. Потом решаешь задачу, велосипедя какое-то решение и понимаешь, что это оно и есть. Ну или читаешь описание и понимаешь, что ты уже это делал сам, а теперь узнал как это называется.

winlook38 ★★
()
Ответ на: комментарий от loyd

with запрещён в strict-моде,

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

использовать «классы» из ES6, ибо паттерны).

Мне классы из ES6 не нужны. Я их не использую, и вряд ли когда нибудь буду.

javaQest
() автор топика
Ответ на: комментарий от loyd

«классы» из ES6

Кстати, это определенный даунгрейд для языка, определенно. В свое время, когда после смоллтока был создан селф, люди сакзали, «это смоллток, только more смоллток, чем сам смоллток». Из этого впоследствии вышли несколько языков, в частности, JS, Lua, Io. И вдруг в JS вводится это дерьмо. Это печально.

javaQest
() автор топика
Ответ на: комментарий от javaQest

я его не использую.

Это де-факто хороший тон сегодня.

Я их не использую, и вряд ли когда нибудь буду.

Как бы мы не любили прототипы, но классовые паттерны ООП разработаны для классовой модели ООП и всякая мишура тут только мешает. И да, в ES6 много других вкусностей (короткая запись функций, строковая интерполяция и т.д.).

loyd
()
Ответ на: комментарий от javaQest

Кстати, это определенный даунгрейд для языка, определенно
И вдруг в JS вводится это дерьмо. Это печально.

Ну дык, js внезапно стал популярным, потянулись сюда вчерашние крестовики/жабисты + отряд студентов, которые лабы на qt писали. А тут им прототипную модель суют. Так что ожидаемо. Но так-то да, жаль, что прогнулись.

loyd
()
Ответ на: комментарий от loyd

короткая запись функций

эти функции неполноценны

строковая интерполяция и т.д.

это конечно, плюс, но я бы не сказал, что это прям ВАУ

Что действительно радует из новшеств, так это Proxy и Promise. Несмотря на то, что реализовано это коряво, это все таки огромный шаг вперед. Все остальное — ненужный хлам. Я не проникся.

javaQest
() автор топика
Ответ на: комментарий от javaQest

эти функции неполноценны

Это чего вдруг? bind на уровне языка уже десяток лет ждут.

Что действительно радует из новшеств, так это Proxy и Promise.

Promise унылое говно, его вообще в стандартной библиотеке быть не должно. Что будет, если введут acync/await? Куча легаси говна на обещаниях. С другой стороны, есть неплохие аналоги async/await на генераторах+Promise.

loyd
()
Ответ на: комментарий от loyd

Это чего вдруг? bind на уровне языка уже десяток лет ждут.

явный байнд есть уже давно, а когда его не было, никто не мешал писать func.call(object)

Самое хреновое то, что стрелочные функции не могут связываться динамически. То есть, обычную функцию статично мы всегда можем связать, а стрелочную динамически — нет.

javaQest
() автор топика

А может нет никакой «стратегии», а? Может это фантом коллективного-бессознательного?

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

TDrive ★★★★★
()
Ответ на: комментарий от javaQest

Большинство паттернов теряет смысл в динамических язычках. Основная идея — сконфигурировать поведение внешним образом (ответственность и прочий SOLID) при этом чтобы система типов по рукам не дала. Вот это и есть паттерны проектирования. Поэтому ты и не понимаешь зачем они нужны.

anonymous
()
Ответ на: комментарий от javaQest

Ну еще можешь глянуть «Рефакторинг» Фаулера. Мотивировку рефакторингов замена кода типа подклассами и замена кода типа стратегией/состоянием.

winlook38 ★★
()
Ответ на: комментарий от TDrive

Не знаю, пока я не понимаю толком. В том, что ты вчера говорил, был какой-то смысл, а тут снова получается тавтология

var Greeter = function(strategy) {
    this.strategy = strategy;
};
индивидуальное поведение объетка === стратегия объекта.

javaQest
() автор топика
Ответ на: комментарий от javaQest

никто не мешал писать func.call(object)

Ну да, а ещё никто не мешал let that = this использовать и медленный Function#bind юзать. Ах да, let не нужен тоже. Ну так может ну его, этот синтаксикс? Давай сразу в разобранный ast писать, даже без лисповых ', : и т.д., а?

loyd
()
Ответ на: комментарий от javaQest

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

TDrive ★★★★★
()
Ответ на: комментарий от loyd

Ну так может ну его, этот синтаксикс?

Между прочим, так оно и есть, было бы идеально. Никто не страдает от отсутствия синтаксиса в tcl, Io, например. Гораздо удобней иметь кастомный синтаксис, нежели захардкоренный. Это конечно не для Ынтерпрайза, но тем не менее.

javaQest
() автор топика
Ответ на: комментарий от TDrive

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

Если в твоем тексте сделать s/контекст/объект, общий смысл от этого не изменится:)

javaQest
() автор топика
Ответ на: комментарий от javaQest

Если в твоем тексте сделать s/контекст/объект, общий смысл от этого не изменится:)

«контекст» это одна из частей паттерна стратегия, абстракция, https://upload.wikimedia.org/wikipedia/ru/4/4c/Strategy_pattern.PNG левая верхняя.

TDrive ★★★★★
()
Ответ на: комментарий от TDrive

Синглтон, интерфейс, прототип, raii и .тд.. Ещё далеки от классики заместитель, компоновщик, адаптер, декоратор и т.д.. Касательно js, реактор и проактор теряют смысл, а ещё паттерны для потоков (всякие мониторы и двойные проверки). Касательно js/dom, mvc теряет смысл (в пользу mvp и mvvm).

loyd
()

При реальных, достаточно сложных стратегиях твой код превратится в нечитаемое говно, т.к. определять развесистые анонимные функции в момент создания инстансов Greeter — безусловный говнокод.

А то, что ты данный конкретный пример вусмерть «заоптимизировал», конечно, безусловное достижение :).

Virtuos86 ★★★★★
()
Ответ на: комментарий от loyd

Синглтон с чего вдруг теряет смысл например в js?

заместитель, компоновщик, адаптер, декоратор и т.д

Все они постоянно используются в том же ruby.

Касательно js/dom, mvc теряет смысл (в пользу mvp и mvvm).

они вообще производные от mvc и их применимость определяется областю применения, а не динамичностью яп.

TDrive ★★★★★
()
Ответ на: комментарий от TDrive

Синглтон с чего вдруг теряет смысл например в js

Потому что есть объектная нотация. Синглтон это не более, чем {..}, ибо по своей сути это модуль, а не объект.

Все они постоянно используются в том же ruby.

Я же написал, что они

далеки от классики

ибо проще сделать адаптер и декоратор относительно функции, просто подменив её, а не для всего объекта, так что тут только название. Заместитель при утиной типизации не требует никакого наследования, всё сильно упрощается относительно классической реализации.

они вообще производные от mvc и их применимость определяется областю применения, а не динамичностью яп.

Совершенно верно, поэтому я уточнил, что речь о js/dom. С другой стороны, возможность в любое время добавлять св-ва и методы к объектам вполне может свести на нет классический mvc (можно определять различные группы св-тв и методов, относящихся к M, V и C отдельно в разных местах, но на одном объекте).

Но, я не отрицаю важность паттернов. Просто нужно смотреть шире, а не только в контексте объектов. Если обобщить эти паттерны на функции, т.е. оставить именно идею, то всё будет применимо и к динамическим языкам.

loyd
()
Ответ на: комментарий от TDrive

«контекст» это одна из частей паттерна стратегия, абстракция,

Любой объект, является, в этом смысле контекстом


theObject.foo
theObject.bar

тут твой контекст — это theObject, а «стратегии» — foo, bar:), кажется я начинаю врубаться. И начинаю врубаться так же, почему это не понятно:), потому что это ни о чем:)

javaQest
() автор топика
Ответ на: комментарий от javaQest

Выше я ссылку оставил. Ты исходишь из того, что в js функции — объекты первого класса, поэтому стратегия действительно под вопросом (ты с лёгкостью в шапке заменил сабж на функциональный аналог). Но если писать в классовом ООП, а не ФП, то...

loyd
()
Ответ на: комментарий от loyd

Синглтон это не более, чем {..}, ибо по своей сути это модуль, а не объект.

синглтон в JS вот так модно выразить

singletone={create: function(){return singletone}}
:)

javaQest
() автор топика
Ответ на: комментарий от loyd

Потому что есть объектная нотация. Синглтон это не более, чем {..}, ибо по своей сути это модуль, а не объект.

Нет, в отличае от {..} у синглтона есть инициализация выполняемая при первом использовании, а {..} тебе надо руками инициализировать + следить что бы он не испольовался до инициалиации, проверок там всяких напихать, эксепшенов + их обработку в местах использования {..}

ибо проще сделать адаптер и декоратор относительно функции, просто подменив её, а не для всего объекта, так что тут только название.

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

Просто нужно смотреть шире, а не только в контексте объектов. Если обобщить эти паттерны на функции, т.е. оставить именно идею, то всё будет применимо и к динамическим языкам.

Почему к динамическим яп не применим контекст объектов? И вообще все паттерны из книги банды четырех придумывались конкретно для ООП, сама книга называется «Приемы объектно ориентированного проектирования». Для функциональшины придумывайте свои паттерны.

TDrive ★★★★★
()
Ответ на: комментарий от loyd

Синглтон это не более, чем {..}

это, как раз не синглтон, конструкция {} каждый раз возвращает новый экземпляр.

Если я правильно понял, о чем речь

javaQest
() автор топика
Ответ на: комментарий от javaQest

Любой объект, является, в этом смысле контекстом

Объект это объект, а контекст это определенная роль в рамках паттерна стратегия. Сравиваешь теплое с мягким.

тут твой контекст — это theObject, а «стратегии» — foo, bar:)

стратегии не связаны с конкретным контекстом, они реализуют единый интерфейс, если этот интерфейс подходит контексту он может заюзать эти стратегии.

TDrive ★★★★★
()
Ответ на: комментарий от TDrive

Ладно. короче я понял все. Просто ты смотришь на это тенденциозно, со своей колокольни, поэтому не понимаешь о чем я говорю. Это вопрос точки зрения. Слова сами по себе не особо важны, важна суть. А суть в том, что любой объект представляет собой контекст, а поведение его — это его стратегия, не важно при этом, как оно реализовано, оно может быть вообще заимствованно извне. Когда мы цепляем какое-либо поведение объекту, оно становиться его поведением.

javaQest
() автор топика
Ответ на: комментарий от javaQest

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

TDrive ★★★★★
()
Ответ на: комментарий от TDrive

тем кто использует синглтон совсем не обязательно знать что это синглтон

А никто и не заставляет знать

более того по ситуации он может не всегда быть синглтоном.

это как?

javaQest
() автор топика
Ответ на: комментарий от javaQest

А суть в том, что любой объект представляет собой контекст, а поведение его — это его стратегия, не важно при этом, как оно реализовано, оно может быть вообще заимствованно извне. Когда мы цепляем какое-либо поведение объекту, оно становиться его поведением.

В зависимости от реализации это либо будет паттерн «Стратегия» либо не будет.

TDrive ★★★★★
()
Ответ на: комментарий от TDrive

Нет, в отличае от {..} у синглтона есть инициализация ...

Соглашусь. Однако паттерн синглтон в любом случае — зло: http://rsdn.ru/forum/design/2615563.flat#2615563.

в общем то он и занимается подменой функций объекта который декарирует, или как ты себе эту подмену представляешь

let a = { foo() { return "a" } };
let foo = a.foo;
a.foo = function() { retrun foo.call(this) + "b"; };

Почему к динамическим яп не применим контекст объектов

Применимо. Но когда нужен, например, прокси, гораздо быстрее сконструировать ограниченный объект на лету, обладающим нужными свойствами и методами, без полноценного наследования.

loyd
()
Ответ на: комментарий от javaQest

это как?

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

TDrive ★★★★★
()
Ответ на: комментарий от loyd

Соглашусь. Однако паттерн синглтон в любом случае — зло

Тем немение есть ситуации в которых его применение оправдано, похожая стуация с goto.

TDrive ★★★★★
()
Ответ на: комментарий от TDrive

Это не всегда так. Большинство реализаций синглтона (напр., крестовые) предполагают получение экземпляра через какой-нибудь getInstance().

loyd
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.