Вопрос по подходу к реализации паттерна стратегия c#
От: corpse56  
Дата: 05.12.19 17:43
Оценка:
Здравствуйте!
Никак не могу определиться, какой подход лучше применить для реализации паттерна стратегия. (может я не тот паттерн выбрал?)
Задача такая. Есть магазин, который продаёт товары. Каждый товар должен продаваться по своему алгоритму. Было решено применить паттерн стратегия. Получилось два варианта. Какой из них более правильный я не пойму. Я приведу оба примера и опишу что смущает.
Вариант 1. Логику продажи каждого товара инкапсулируем в класс магазина, который наследуем от интерфейса:
using System;                    
public class Program
{
    public static void Main()
    {
        Shop shop = new Shop();
        var a = new A("A");
        shop.Sell(a);
        var b = new B("B");
        shop.Sell(b);
    }
}
interface IShop
{
    void Sell(A a);
    void Sell(B b);
}
class baseClass
{
    public string Name;
}
class A : baseClass
{
    public A(string s)
    {
        this.Name = s;
    }
}
class B : baseClass
{
    public B(string s)
    {
        this.Name = s;
    }    
}
class Shop : IShop
{
    public void Sell(A a)
    {
        Console.WriteLine("sell AAA"+a.Name);
    }
    public void Sell(B b)
    {
        Console.WriteLine("sell BBB"+b.Name);
    }
}

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

Вариант 2. Логику продажи каждого товара икапсулируем в сам товар:
using System;
using System.Collections.Generic;                    
public class Program
{
    public static void Main()
    {
        List<baseClass> list = new List<baseClass> { new A("A"), new B("B"), new B("B"), new A("A") };
        Shop shop = new Shop();
        foreach(baseClass item in list)
        {
            shop.seller = item.seller;
            shop.seller.Sell(item);//это эквивалентно    item.seller.Sell(item);
        }
    }
}

class Shop
{
    public ISellable seller;
}

interface ISellable
{
    void Sell(baseClass a);
}
class baseClass
{
    public string Name;
    public ISellable seller;
}
class A : baseClass
{
    
    public A(string s)
    {
        this.Name = s;
        seller = new SellerA();
    }
    
}
class B : baseClass
{
    public B(string s)
    {
        this.Name = s;
        seller = new SellerB();
    }    
    
}
class SellerA : ISellable
{
    public void Sell(baseClass a)
    {
        Console.WriteLine("sell AAA"+a.Name);
    } 
}
class SellerB : ISellable
{
    public void Sell(baseClass b)
    {
        Console.WriteLine("sell BBB"+b.Name);
    } 
}

Здесь смущает то, что продаёт-то магазин! А не товар сам себя продаёт! shop.seller.Sell(item); === item.seller.Sell(item); Зачем тогда класс магазина вообще нужен? Нет, ну, конечно, я описываю абстрактную ситуацию, и класс магазина описывает ещё полно всякого поведения и параметров. Но в данном конкретном примере получается, что товар продаёт сам себя. И только искусственно если добавить ссылку в магазин на интервейс, то типа будет выглядеть как-будто продаёт магазин. Ещё смущает то, что нужно присваивать каждый раз нужный интерфейс перед продажей. Ну или не присваивать, а сказать товару, чтобы продал сам себя, а он ещё и ссылку на себя получает.

Я понимаю, что вопрос тот ещё. Но может всё-таки я где-то блуждаю не там?
Что можно сказать про "магазин"? Типов товаров будет немного, всего около 7-8. Ещё магазин должен будет каждый товар уметь принимать на склад, принимать бракованый товар назад, отсылать товар в ремонт и т.д.
Даже этот список дейтсвий помножить на 7 получится ~30 методов в IShop для первого примера. А для второго примера получится, что не магазин управляет товаром, а товар управляет сам собой ...
Лично мне больше нравится второй пример, если б не то обстоятельство, что товар сам себя "обслуживает". Или это нормально? Посоветуйте, пожалуйста, что-нибудь! Может другой паттерн или где-то я ошибся в реализации?
использую c#
Спасибо.
Re: Вопрос по подходу к реализации паттерна стратегия c#
От: Carc Россия https://vk.com/gosha_mazov
Дата: 05.12.19 19:41
Оценка: 2 (1) +1
Здравствуйте, corpse56, Вы писали:

C>Здравствуйте!

C>Никак не могу определиться, какой подход лучше применить для реализации паттерна стратегия. (может я не тот паттерн выбрал?)C>Спасибо.

По моему тут не через паттерн "стратегия" нужно делать, а через паттерн "визитер".

Или же заводить еще один интерфейс "покупка" (ну или "продажа"), который завязан на два других интерфейса. "Магазин" и "товар". Через параметры, или ссылки.

Явно же напрашивается третья сущность…
Aml Pages Home
Re: Вопрос по подходу к реализации паттерна стратегия c#
От: Qulac Россия  
Дата: 05.12.19 21:21
Оценка: +1
Здравствуйте, corpse56, Вы писали:

C>Здравствуйте!

C>Никак не могу определиться, какой подход лучше применить для реализации паттерна стратегия. (может я не тот паттерн выбрал?)
C>Задача такая. Есть магазин, который продаёт товары. Каждый товар должен продаваться по своему алгоритму. Было решено применить паттерн стратегия.
C>использую c#
C>Спасибо.

Стратегия используется тогда, когда способ может меняться "динамически", т.е. товар продавался одним способом, а потом этот способ поменяли на другой. Если один тип товара всегда продается одним и тем же способом, то стратегия не нужна.
Программа – это мысли спрессованные в код
Re: Вопрос по подходу к реализации паттерна стратегия c#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 05.12.19 22:08
Оценка: 1 (1) +1
Здравствуйте, corpse56, Вы писали:

C>Здравствуйте!

C>Никак не могу определиться, какой подход лучше применить для реализации паттерна стратегия. (может я не тот паттерн выбрал?)
C>Задача такая. Есть магазин, который продаёт товары. Каждый товар должен продаваться по своему алгоритму. Было решено применить паттерн стратегия. Получилось два варианта. Какой из них более правильный я не пойму. Я приведу оба примера и опишу что смущает.
Дело не в паттерне или подходе. Сперва нужно сформулировать проблему. В условии я вижу предпосылку для применения стратегии, но проблемы в нем не содержится. "Каждый товар должен продаваться по своему алгоритму". Это лишь слова, а не способ реализации. Из слов "товар должен продаваться" не следует что у товара будет метод "ПродайСебя". Включим фантазию и представим, что надо продавать 3 единицы по цене двух. У какой из 3-х единиц вызывать метод продажи? Почему это вообще метод товара?

C>Здесь смущает то, что продаёт-то магазин! А не товар сам себя продаёт! shop.seller.Sell(item); === item.seller.Sell(item); Зачем тогда класс магазина вообще нужен? Нет, ну, конечно, я описываю абстрактную ситуацию, и класс магазина описывает ещё полно всякого поведения и параметров. Но в данном конкретном примере получается, что товар продаёт сам себя. И только искусственно если добавить ссылку в магазин на интервейс, то типа будет выглядеть как-будто продаёт магазин. Ещё смущает то, что нужно присваивать каждый раз нужный интерфейс перед продажей. Ну или не присваивать, а сказать товару, чтобы продал сам себя, а он ещё и ссылку на себя получает.


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

C>Я понимаю, что вопрос тот ещё. Но может всё-таки я где-то блуждаю не там?

C>Что можно сказать про "магазин"? Типов товаров будет немного, всего около 7-8. Ещё магазин должен будет каждый товар уметь принимать на склад, принимать бракованый товар назад, отсылать товар в ремонт и т.д.
А могло бы быть 7-8 тысяч товаров. Разве должен код софта магазина быть заточен на малое кол-во товаров? И ту не понятно, почему разные алгоритмы приема на склад? Пришел и ладно.

C>Даже этот список дейтсвий помножить на 7 получится ~30 методов в IShop для первого примера. А для второго примера получится, что не магазин управляет товаром, а товар управляет сам собой ...

C>Лично мне больше нравится второй пример, если б не то обстоятельство, что товар сам себя "обслуживает". Или это нормально? Посоветуйте, пожалуйста, что-нибудь! Может другой паттерн или где-то я ошибся в реализации?
Это вообще реальная задача, или упражнение на тему "придумайте, куда присобачить стратегию в магазине"?
Re: Вопрос по подходу к реализации паттерна стратегия c#
От: Sharov Россия  
Дата: 06.12.19 09:56
Оценка:
Здравствуйте, corpse56, Вы писали:

C>Я понимаю, что вопрос тот ещё. Но может всё-таки я где-то блуждаю не там?

C>Что можно сказать про "магазин"? Типов товаров будет немного, всего около 7-8. Ещё магазин должен будет каждый товар уметь принимать на склад, принимать бракованый товар назад, отсылать товар в ремонт и т.д.
C>Даже этот список дейтсвий помножить на 7 получится ~30 методов в IShop для первого примера. А для второго примера получится, что не магазин управляет товаром, а товар управляет сам собой ...
C>Лично мне больше нравится второй пример, если б не то обстоятельство, что товар сам себя "обслуживает". Или это нормально? Посоветуйте, пожалуйста, что-нибудь! Может другой паттерн или где-то я ошибся в реализации?
C>использую c#
C>Спасибо.

А почему не:

class Shop : IShop
{
    public void Sell(ISeller seller)
    {

    }
}


Товары продавать должен все-таки магазин, но у каждого товара может быть своя специфика.
Кодом людям нужно помогать!
Re: Вопрос по подходу к реализации паттерна стратегия c#
От: Vladek Россия Github
Дата: 06.12.19 12:41
Оценка: 1 (1) -2
Здравствуйте, corpse56, Вы писали:

C>Никак не могу определиться, какой подход лучше применить для реализации паттерна стратегия. (может я не тот паттерн выбрал?)

C>Задача такая. Есть магазин, который продаёт товары. Каждый товар должен продаваться по своему алгоритму. Было решено применить паттерн стратегия. Получилось два варианта. Какой из них более правильный я не пойму. Я приведу оба примера и опишу что смущает.
C>Вариант 1. Логику продажи каждого товара инкапсулируем в класс магазина, который наследуем от интерфейса:
C>Здесь смущает то, что класс магазина будет большой, и должен описывать схему продажи (и не только) каждого товара.

C>Вариант 2. Логику продажи каждого товара икапсулируем в сам товар:

C>Здесь смущает то, что продаёт-то магазин! А не товар сам себя продаёт! shop.seller.Sell(item); === item.seller.Sell(item); Зачем тогда класс магазина вообще нужен? Нет, ну, конечно, я описываю абстрактную ситуацию, и класс магазина описывает ещё полно всякого поведения и параметров. Но в данном конкретном примере получается, что товар продаёт сам себя. И только искусственно если добавить ссылку в магазин на интервейс, то типа будет выглядеть как-будто продаёт магазин. Ещё смущает то, что нужно присваивать каждый раз нужный интерфейс перед продажей. Ну или не присваивать, а сказать товару, чтобы продал сам себя, а он ещё и ссылку на себя получает.

В ООП товар продаёт сам себя, потому что только сам товар располагает всей нужной информацией о сделке. Моделировать продажу можно как угодно, но в рамках ООП поведение и состояние должны быть вместе — причём, всё определяется здравым смыслом, а не догмами и канонами. Смысл в том, чтобы писать компактный код, который решает задачу и удобен для изменений в будущем. Если абстракции нет места, то она не нужна — поэтому такого класса как Магазин может и не быть вовсе.

Выглядеть это должно так: у класса товара должен быть метод Sell, в который передаётся только необходимая информация для завершения сделки. Реализация этого метода может быть любой: например, товар знает к какой категории он относится и уже передаёт управление ей для продажи. Отдельная категория товаров реализует свой метод продажи.

C>Я понимаю, что вопрос тот ещё. Но может всё-таки я где-то блуждаю не там?

C>Что можно сказать про "магазин"? Типов товаров будет немного, всего около 7-8. Ещё магазин должен будет каждый товар уметь принимать на склад, принимать бракованый товар назад, отсылать товар в ремонт и т.д.

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

C>Даже этот список дейтсвий помножить на 7 получится ~30 методов в IShop для первого примера. А для второго примера получится, что не магазин управляет товаром, а товар управляет сам собой ...


В адекватных решаемой задаче абстракциях количество публичных методов небольшое, код становится логичным и лаконичным.
Re[2]: Вопрос по подходу к реализации паттерна стратегия c#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 06.12.19 12:45
Оценка:
Здравствуйте, Vladek, Вы писали:

V>В ООП товар продаёт сам себя, потому что только сам товар располагает всей нужной информацией о сделке. Моделировать продажу можно как угодно, но в рамках ООП поведение и состояние должны быть вместе — причём, всё определяется здравым смыслом, а не догмами и канонами. Смысл в том, чтобы писать компактный код, который решает задачу и удобен для изменений в будущем. Если абстракции нет места, то она не нужна — поэтому такого класса как Магазин может и не быть вовсе.


V>Выглядеть это должно так: у класса товара должен быть метод Sell, в который передаётся только необходимая информация для завершения сделки. Реализация этого метода может быть любой: например, товар знает к какой категории он относится и уже передаёт управление ей для продажи. Отдельная категория товаров реализует свой метод продажи.


Если нужно продать 3 товара по цене двух, то у какого из них вызывать метод Sell?
Re[3]: Вопрос по подходу к реализации паттерна стратегия c#
От: Vladek Россия Github
Дата: 06.12.19 13:08
Оценка: -1
Здравствуйте, samius, Вы писали:

S>Если нужно продать 3 товара по цене двух, то у какого из них вызывать метод Sell?


Один объект, один вызов. Разумно предположить, что этот объект представляет сразу сам товар, и его количество, и все дополнительные правила продажи.
Re[4]: Вопрос по подходу к реализации паттерна стратегия c#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 06.12.19 13:49
Оценка: 1 (1)
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, samius, Вы писали:


S>>Если нужно продать 3 товара по цене двух, то у какого из них вызывать метод Sell?


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

А если акция распространяется не на товар, а на подмножество товаров? За веревку и мыло туалетная бумага в подарок Разумно предположить, что вызывая метод Sell у веревки, мыла и бумаги по отдельности, условия акции мы не сможем проверить. Да и какой из товаров должен будет знать о наличии акции на все 3?
Re[5]: Вопрос по подходу к реализации паттерна стратегия c#
От: Vladek Россия Github
Дата: 06.12.19 13:58
Оценка: -1
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Vladek, Вы писали:


V>>Здравствуйте, samius, Вы писали:


S>>>Если нужно продать 3 товара по цене двух, то у какого из них вызывать метод Sell?


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

S>А если акция распространяется не на товар, а на подмножество товаров? За веревку и мыло туалетная бумага в подарок Разумно предположить, что вызывая метод Sell у веревки, мыла и бумаги по отдельности, условия акции мы не сможем проверить. Да и какой из товаров должен будет знать о наличии акции на все 3?

Значит надо моделировать корзину товаров, которая умеет выбирать нужную акцию в зависимости от сочетания товаров. Абстракция должна быть адекватной, а не универсальной.
Re[6]: Вопрос по подходу к реализации паттерна стратегия c#
От: Carc Россия https://vk.com/gosha_mazov
Дата: 06.12.19 14:21
Оценка: 1 (1) +1
Здравствуйте, Vladek, Вы писали:



S>>А если акция распространяется не на товар, а на подмножество товаров? За веревку и мыло туалетная бумага в подарок Разумно предположить, что вызывая метод Sell у веревки, мыла и бумаги по отдельности, условия акции мы не сможем проверить. Да и какой из товаров должен будет знать о наличии акции на все 3?


V>Значит надо моделировать корзину товаров, которая умеет выбирать нужную акцию в зависимости от сочетания товаров. Абстракция должна быть адекватной, а не универсальной.

samius Вам дело говорит… Ни к чему здесь всё тащить в товар! Тут явно есть третья сущность, как уже писал выше.
Ну не может товар знать на складе он, или уже как списанка на помойке лежит — ибо ему это не нужно. Опять же как себя продать — товар не должен знать, не его ответственность — у него только набор характеристик: чего, сколько, вес в храммах, толщина, ширина, срок годности ну и цена само собой.

Третья сущность (объект, интерфейс)
Условно назовем ее "сделка" (дабы не спорить "продажа" или "покупка").

Вот к ней, к третьей сущности, и применимы все другие параметры.

Например:
1) Была скидка или нет.
2) Товар с доставкой или нет.
3) "Сделка" (продажа) отменена или нет (товар не доставлен, клиент отказался и.т.д.)

А пихать все в "товар" это просто нарушение абстракции.
Товар не может знать как себя продать, потому как сам себя товар не продает.

Товар вообще всего лишь сущность описывающая сам товар: что это? Диван? Лицензионный ключик для софта? Жратва из Яндекс-Кушать?
Т.е. набор атрибутов, в том числе и цена.

А все остальное уже разруливает эта самая третья сущность — "сделка"

Наример
1) Есть ли скидка (проверяет где-то там в объекте "магазин".
2) Можно ли вообще продать? (к примеру, есть ли на складе).
3) Статус сделки. Например: "товар доставлен", "нет на складе", "в обработке" и.т.д.

Иначе действительно вермишель получается — все в одну кучу.
А эта самая "сделка" по сути своей композит — всё увязывает в единое целое. Дергая другие объекты ("склад" есть ли вообще), "акции" (давать ли скидку), способ оплаты (принимаем монгольские тугры, или берем только мешками репчатого лука)…
Aml Pages Home
Отредактировано 06.12.2019 14:22 Carc . Предыдущая версия .
Re[6]: Вопрос по подходу к реализации паттерна стратегия c#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 06.12.19 15:43
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, samius, Вы писали:


S>>А если акция распространяется не на товар, а на подмножество товаров? За веревку и мыло туалетная бумага в подарок Разумно предположить, что вызывая метод Sell у веревки, мыла и бумаги по отдельности, условия акции мы не сможем проверить. Да и какой из товаров должен будет знать о наличии акции на все 3?


V>Значит надо моделировать корзину товаров, которая умеет выбирать нужную акцию в зависимости от сочетания товаров. Абстракция должна быть адекватной, а не универсальной.


Согласен. Так гораздо гибче, чем товар.Продайся().
Re: Вопрос по подходу к реализации паттерна стратегия c#
От: Слава  
Дата: 06.12.19 17:25
Оценка: 9 (1) +1 :)
Здравствуйте, corpse56, Вы писали:

C>Никак не могу определиться, какой подход лучше применить для реализации паттерна стратегия. (может я не тот паттерн выбрал?)


Потому что по-факту, когда анализ бизнес-процессов показывает, что процессов нет — у тебя ДОКУМЕНТ НИ О ЧЁМ.
А когда ты имеешь документ ни о чём — ты спокойно называешь его "СТРАТЕГИЯ".

  источник
https://sapforum.pro/forum/viewtopic.php?f=18&amp;t=15784&amp;start=1725
https://youtu.be/KF4g_Ks3d4I

Извините, музыкой навеяло. Может вы вообще не тот путь выбрали, в 2019 году какие-то "стратегии" вспоминать из дремучих С++ начала 90х? Это при наличии Action и Func, и при том, что "стратегии" продаж будут конфигурироваться в конфигурации, в GUI. И вам скорее всего потребуется нечто вроде интерпретатора правил.
Отредактировано 06.12.2019 17:27 Слава . Предыдущая версия .
Re[7]: Вопрос по подходу к реализации паттерна стратегия c#
От: Vladek Россия Github
Дата: 06.12.19 18:37
Оценка: 1 (1)
Здравствуйте, Carc, Вы писали:

C>Здравствуйте, Vladek, Вы писали:




S>>>А если акция распространяется не на товар, а на подмножество товаров? За веревку и мыло туалетная бумага в подарок Разумно предположить, что вызывая метод Sell у веревки, мыла и бумаги по отдельности, условия акции мы не сможем проверить. Да и какой из товаров должен будет знать о наличии акции на все 3?


V>>Значит надо моделировать корзину товаров, которая умеет выбирать нужную акцию в зависимости от сочетания товаров. Абстракция должна быть адекватной, а не универсальной.

C>samius Вам дело говорит… Ни к чему здесь всё тащить в товар! Тут явно есть третья сущность, как уже писал выше.

C>Ну не может товар знать на складе он, или уже как списанка на помойке лежит — ибо ему это не нужно.

Откуда это утверждение?
C>Опять же как себя продать — товар не должен знать, не его ответственность — у него только набор характеристик: чего, сколько, вес в храммах, толщина, ширина, срок годности ну и цена само собой.

Я уже написал, что поведение и состояние в ООП должны быть вместе. А во всём остальном — никто никому ничего не должен. Абстракция должна быть удобной, от этого зависит лаконичность и выразительность кода, который обслуживает эту абстракцию.

C>Третья сущность (объект, интерфейс)

C>Условно назовем ее "сделка" (дабы не спорить "продажа" или "покупка").
Что повлекло её добавление?

C>Вот к ней, к третьей сущности, и применимы все другие параметры.


C>Например:

C>1) Была скидка или нет.
C>2) Товар с доставкой или нет.
C>3) "Сделка" (продажа) отменена или нет (товар не доставлен, клиент отказался и.т.д.)

Что значит применимы параметры? Это какая-то деталь, выточенная на станке по шаблону, что к ней можно применять какие-то параметры?

C>А пихать все в "товар" это просто нарушение абстракции.


Абстракция — чистая идея, выраженная в коде. Что такое нарушение абстракции, если она может быть любой, а её критерии отбора я уже указал: адекватность решаемой задачи, удобство использования.

C>Товар не может знать как себя продать, потому как сам себя товар не продает.


Откуда это ограничение проистекает?

C>Товар вообще всего лишь сущность описывающая сам товар: что это? Диван? Лицензионный ключик для софта? Жратва из Яндекс-Кушать?

C>Т.е. набор атрибутов, в том числе и цена.

C>А все остальное уже разруливает эта самая третья сущность — "сделка"


C>Наример

C>1) Есть ли скидка (проверяет где-то там в объекте "магазин".
C>2) Можно ли вообще продать? (к примеру, есть ли на складе).
C>3) Статус сделки. Например: "товар доставлен", "нет на складе", "в обработке" и.т.д.

C>Иначе действительно вермишель получается — все в одну кучу.

C>А эта самая "сделка" по сути своей композит — всё увязывает в единое целое. Дергая другие объекты ("склад" есть ли вообще), "акции" (давать ли скидку), способ оплаты (принимаем монгольские тугры, или берем только мешками репчатого лука)…

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

Ещё раз: универсальность не нужна, нужна адекватность. Универсальность абстракций ведёт к росту спонтанной сложности программы.

Brooks distinguishes between two different types of complexity: accidental complexity and essential complexity. Accidental complexity relates to problems which engineers create and can fix; for example, the details of writing and optimizing assembly code or the delays caused by batch processing. Essential complexity is caused by the problem to be solved, and nothing can remove it; if users want a program to do 30 different things, then those 30 things are essential and the program must do those 30 different things.

Re[8]: Вопрос по подходу к реализации паттерна стратегия c#
От: Carc Россия https://vk.com/gosha_mazov
Дата: 06.12.19 19:09
Оценка:
Здравствуйте, Vladek, Вы писали:


C>>Ну не может товар знать на складе он, или уже как списанка на помойке лежит — ибо ему это не нужно.

V>Откуда это утверждение?

Потому что "на складе", "не на складе" это не свойство объекта "товар".
Здесь типичная композиция — HasIs.
В данном случае это как раз свойство объекта "склад".
Т.е. это "склад" владеет "товаром", а не свойство "товара" — "на складе" или "нет".
Aml Pages Home
Re[8]: Вопрос по подходу к реализации паттерна стратегия c#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 06.12.19 19:19
Оценка: 1 (1) +1
Здравствуйте, Vladek, Вы писали:

V>Я уже написал, что поведение и состояние в ООП должны быть вместе.

Что именно значит "вместе"? И откуда это следует?
Re[8]: Вопрос по подходу к реализации паттерна стратегия c#
От: Carc Россия https://vk.com/gosha_mazov
Дата: 06.12.19 19:21
Оценка: 1 (1) +2
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, Carc, Вы писали:


C>>Третья сущность (объект, интерфейс)

C>>Условно назовем ее "сделка" (дабы не спорить "продажа" или "покупка").
V>Что повлекло её добавление?

Потому что у "сделки" ("продажи", "покупки" или как там назовем) есть свои собственное свойства. Которых нет у других (магазин, товар).

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

Например, сегодня скидки есть, завтра нет. Скидка есть если товаров больше икс заказано, или у покупателя есть код купона. Или это старинный клиент и него по жизни "скидка". И.т.д.

И куда все это вкладывать хотите? В товар?
С какого? В случае тех же скидок сегодня\завтра\больше 3-х заказанных — каким боком это относится к "товару"? Никаким.

Тогда, допустим сделаем эти скидки свойством "магазина"… Тоже каким боком?
А если, скидка для старинного клиента (да та же скидка для продления лицензии на софт к примеру).
Причем тут весь объект\интерфейс "магазин"?

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

Вот эти взаимоотношения и может инкапсулировать отдельная сущность — "сделка"
Aml Pages Home
Re[8]: Вопрос по подходу к реализации паттерна стратегия c#
От: Carc Россия https://vk.com/gosha_mazov
Дата: 06.12.19 19:39
Оценка: +1
Здравствуйте, Vladek, Вы писали:
V>Абстракция — чистая идея, выраженная в коде.

Абстракция должна быть абстрактной. А удобной она быть и вовсе не обязана.
Удобным должен быть интерфейс к ее свойствам.

Главное в абстрации ничего лишнего. А то это как раз и будет взрывной рост сложности.

Про тот же пример: что значит метод "Товар.ПродайСебя"?

А цена (со скидками или без)? Откуда "Товар…" Знает про скидки?
А есть ли товар в наличии? (на складе или отсутствует). Откуда сущность "товар" может знать на складе она или нет.

V>Что такое нарушение абстракции, если она может быть любой, а её критерии отбора я уже указал: адекватность решаемой задачи, удобство использования.

Где тут в обсуждении было "любая абстракция"?

Была только третья сущность — "сделка".

А "удобство использования" это и вовсе "в огороде бузина, а в Киеве дядька".
Чтобы скрыть детали, и сделать более удобным использование используют другие паттерны: Facade, Slice.
Но они не части самой абстракции..

В общем, Вам тут хорошо посоветовали. Пока Вы будете пытаться моделировать объекты, а не бизнес-процессы — у Вас будет получаться все эта муть.

Если приглядеться, процессы и так торчат отовсюду в вашем изначальном варианте. Только криво и сбоку: "Товар.ПродайСебя", "Корзина.ПримениСкидку" .

Имхо, здесь нужно моделировать процессы, а "товары", "скидки", "магазины", "скады" будут их аргументами. Аргументами сущности, которая моделирует процесс. В моем примере, это может быть сущность "сделка".

А не наоборот. Тогда все начнет более-менее вставать на свои места.
Aml Pages Home
Re: Вопрос по подходу к реализации паттерна стратегия c#
От: Cyberax Марс  
Дата: 07.12.19 08:41
Оценка: +5
Здравствуйте, corpse56, Вы писали:

C>Никак не могу определиться, какой подход лучше применить для реализации паттерна стратегия.

Это вопрос чисто теоретический или практический?

Если практический, то не используем никаких нафиг там стратегий, а пишем тупой код с if'ами для разных типов товаров. После того, как будут написаны (как минимум) продажи для 3 типов товаров, то смотрим, что можно объединить и абстрагировать.
Sapienti sat!
Re: Вопрос по подходу к реализации паттерна стратегия c#
От: v.a.v СССР  
Дата: 07.12.19 10:19
Оценка: 2 (2)
Здравствуйте, corpse56, Вы писали:

C>Здравствуйте!

C>Никак не могу определиться, какой подход лучше применить для реализации паттерна стратегия. (может я не тот паттерн выбрал?)
C>Задача такая. Есть магазин, который продаёт товары. Каждый товар должен продаваться по своему алгоритму. Было решено применить паттерн стратегия. Получилось два варианта. Какой из них более правильный я не пойму.

Возможно стоит применить таблицу правил.
Если у вас именно "магазин, который продаёт товары", то есть каждый товар подается отдельно, тогда применяем таблицу правил продажи к "товар"("товар" далее называем "контекст продажи").
Если предусмотрен некий контекст (корзина покупателя, сделка ..),тогда применяем таблицу правил продажи к "корзина покупателя"("корзина покупателя" далее называем "контекст продажи").
Таблица правил в простой реализации, это список состоящий из экземпляров класса "правило".
При продаже проходим по таблице правил и применяем первое, которые удовлетворяет текущему "контекст продажи".
Класс "правило" содержит поля "предикат" и "действие".
"предикат" принимает на вход "контекст продажи", и возвращает результат (bool), как необходимость применения правила.
"действие" также принимает на вход "контекст продажи" и выполняет действие(например формирует или изменяет объект класса "товарная накладная"), которое необходимо выполнить в случае применения правила.
Возможны более сложные и гибкие варианты. Например можно выполнить не только первое а все правила в которых предикат вернул true. Правило может иметь возможность указывать номер следующего правила для сравнения. Таблиц правил может быть несколько, и так далее.
Этот принцип применяется в том числе при реализации firewall(например в linux).
Re[9]: Вопрос по подходу к реализации паттерна стратегия c#
От: Vladek Россия Github
Дата: 07.12.19 10:50
Оценка:
Здравствуйте, Carc, Вы писали:

C>Здравствуйте, Vladek, Вы писали:



C>>>Ну не может товар знать на складе он, или уже как списанка на помойке лежит — ибо ему это не нужно.

V>>Откуда это утверждение?

C>Потому что "на складе", "не на складе" это не свойство объекта "товар".

C>Здесь типичная композиция — HasIs.
C>В данном случае это как раз свойство объекта "склад".
C>Т.е. это "склад" владеет "товаром", а не свойство "товара" — "на складе" или "нет".

В ООП объекты моделируются как это удобно: угол, под которым мы смотрим на совокупность данных, которыми оперирует программа, может быть любым. Условия задачи определяют, что какие данные будут частью состояния объекта.

Более того, некоторые данные будут представляться в разных объектах одновременно, если это позволяет создавать компактные и адекватные объекты вместо больших и неуклюжих "универсальных" объектов, основная задача которых соответствовать предубеждениям программиста "о том как оно всё должно быть", а не решать задачу.
Re[9]: Вопрос по подходу к реализации паттерна стратегия c#
От: Vladek Россия Github
Дата: 07.12.19 10:52
Оценка: 1 (1)
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Vladek, Вы писали:


V>>Я уже написал, что поведение и состояние в ООП должны быть вместе.

S>Что именно значит "вместе"? И откуда это следует?

Гради Буч давно написал классический труд, там всё расписано: https://www.ozon.ru/context/detail/id/3905587/
Re[10]: Вопрос по подходу к реализации паттерна стратегия c#
От: Carc Россия https://vk.com/gosha_mazov
Дата: 07.12.19 11:14
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, samius, Вы писали:


S>>Здравствуйте, Vladek, Вы писали:


V>>>Я уже написал, что поведение и состояние в ООП должны быть вместе.

S>>Что именно значит "вместе"? И откуда это следует?

V>Гради Буч давно написал классический труд, там всё расписано: https://www.ozon.ru/context/detail/id/3905587/

"Вместе" не значит "все впихнуть в одно".

То что поведение завязано на состояние, это и так понятно. Иначе нет никакого поведения просто — потому что оно (поведение) постоянно и ни от чего не зависит… Но увязывать состояние и поведение в коде — это точно не значит сложить все в один интерфейс\объект.
Aml Pages Home
Re[10]: Вопрос по подходу к реализации паттерна стратегия c#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 07.12.19 12:19
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, samius, Вы писали:


V>>>Я уже написал, что поведение и состояние в ООП должны быть вместе.

S>>Что именно значит "вместе"? И откуда это следует?

V>Гради Буч давно написал классический труд, там всё расписано: https://www.ozon.ru/context/detail/id/3905587/


Почему за пояснением своего тезиса вы отсылаете меня к Бучу? Я точно не буду его читать, что бы выяснить, что вы имели в виду.
Re[11]: Вопрос по подходу к реализации паттерна стратегия c#
От: Vladek Россия Github
Дата: 08.12.19 13:07
Оценка: -2
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Vladek, Вы писали:


V>>Здравствуйте, samius, Вы писали:


V>>>>Я уже написал, что поведение и состояние в ООП должны быть вместе.

S>>>Что именно значит "вместе"? И откуда это следует?

V>>Гради Буч давно написал классический труд, там всё расписано: https://www.ozon.ru/context/detail/id/3905587/


S>Почему за пояснением своего тезиса вы отсылаете меня к Бучу? Я точно не буду его читать, что бы выяснить, что вы имели в виду.


Потому что нужна целая книга, чтобы описать ООП. И читать её надо обязательно.
Re[12]: Вопрос по подходу к реализации паттерна стратегия c#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 08.12.19 15:12
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, samius, Вы писали:


S>>Почему за пояснением своего тезиса вы отсылаете меня к Бучу? Я точно не буду его читать, что бы выяснить, что вы имели в виду.


V>Потому что нужна целая книга, чтобы описать ООП. И читать её надо обязательно.

Что бы потом стесняться аргументации своих тезисов?
Re[13]: Вопрос по подходу к реализации паттерна стратегия c#
От: Vladek Россия Github
Дата: 09.12.19 04:19
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Vladek, Вы писали:


V>>Здравствуйте, samius, Вы писали:


S>>>Почему за пояснением своего тезиса вы отсылаете меня к Бучу? Я точно не буду его читать, что бы выяснить, что вы имели в виду.


V>>Потому что нужна целая книга, чтобы описать ООП. И читать её надо обязательно.

S>Что бы потом стесняться аргументации своих тезисов?

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

Выяснить, какую роль играют поведение, состояние и идентичность объектов в ООП, не составляет никакого труда.
Re[14]: Вопрос по подходу к реализации паттерна стратегия c#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.12.19 04:52
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, samius, Вы писали:


V>>>Потому что нужна целая книга, чтобы описать ООП. И читать её надо обязательно.

S>>Что бы потом стесняться аргументации своих тезисов?

V>Делать мне больше нечего, чем в очередной раз спорить о том как моделировать предметную область в ООП. Поищите мои сообщения в этом форуме, споры со сторонниками анемичных моделей и примитивного процедурного программирования я не поддерживаю — что мне с того, что люди регрессируют в процедурное программирование, когда надо думать и проектировать модели? Плохой программист создаёт два новых рабочих места в год.

Все, все. Пойду создавать новые рабочие места. Кому-то же надо этим заниматься.

V>Выяснить, какую роль играют поведение, состояние и идентичность объектов в ООП, не составляет никакого труда.

Я хотел выяснить немного другое. Что значит что поведение и состояние в ООП должны быть вместе и почему логику продажи в труООП надо совать в товар.
Re[4]: Вопрос по подходу к реализации паттерна стратегия c#
От: varenikAA  
Дата: 09.12.19 07:24
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, samius, Вы писали:


S>>Если нужно продать 3 товара по цене двух, то у какого из них вызывать метод Sell?


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


type Product = {
    Price : decimal
}

type OrderLine = {
    Product : Product
    Count : int
    Discount : decimal
}

type Order = {
    Client : string
    Lines : list[OrderLine]
}

type ISaleService = {
    CreateOrder : (string, list[OrderLine]) -> Order
    AddLineToOrder : ...
    Sell : ...
}


Короче, думаю, надо отталкиваться от реальной схемы.
Например, проданный товар нельзя продать(разные сущности).
Схема продажи(алгоритм расчета стоимости может быть выражен через аргумент в виде делегата-функции,
принимающей наименование товара/код, количество, способ оплаты, скидку и т.п.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[2]: Вопрос по подходу к реализации паттерна стратегия c#
От: corpse56  
Дата: 09.12.19 08:39
Оценка:
Здравствуйте, Cyberax, Вы писали:


C>Это вопрос чисто теоретический или практический?


Практический!

C>Если практический, то не используем никаких нафиг там стратегий, а пишем тупой код с if'ами для разных типов товаров. После того, как будут написаны (как минимум) продажи для 3 типов товаров, то смотрим, что можно объединить и абстрагировать.


Да вот нечто такое уже есть и хочется от if'ов избавиться. Но я ума не приложу как это сделать иначе, чем ссылку на логику продажи пихнуть в товар. То есть при создании товара создавать нужного seller'a и хранить его в товаре. И когда надо — применять. Если этого не делать, то как выбирать нужного seller'a? Допустим возьмём предложенный подход с третьей сущностью — сделка. В сделке будет метод Sell. Получается он должен принимать товар и алгоритм продажи. Так вот мне непонятно, откуда возьмётся нужный алгоритм продажи?

class Deal
{
    void MakeSellDeal(baseClass a, ISeller seller)
    {
        seller.Sell(a);
    }
}


Ведь неизвестно какой тип товара... Только если товар при создании создавал бы в себе нужный seller. А иначе придётся проверять тип товара if'ами?
Но в топике некоторые несогласны с таким подходом, утверждая, что товар сам себя не продаёт. Я согласен в принципе с этим, но как сделать по-другому, без if'ов и без того, чтобы seller был свойством товара я не понимаю.
Re[2]: Вопрос по подходу к реализации паттерна стратегия c#
От: corpse56  
Дата: 09.12.19 08:42
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Здравствуйте, corpse56, Вы писали:


C>>Я понимаю, что вопрос тот ещё. Но может всё-таки я где-то блуждаю не там?

C>>Что можно сказать про "магазин"? Типов товаров будет немного, всего около 7-8. Ещё магазин должен будет каждый товар уметь принимать на склад, принимать бракованый товар назад, отсылать товар в ремонт и т.д.
C>>Даже этот список дейтсвий помножить на 7 получится ~30 методов в IShop для первого примера. А для второго примера получится, что не магазин управляет товаром, а товар управляет сам собой ...
C>>Лично мне больше нравится второй пример, если б не то обстоятельство, что товар сам себя "обслуживает". Или это нормально? Посоветуйте, пожалуйста, что-нибудь! Может другой паттерн или где-то я ошибся в реализации?
C>>использую c#
C>>Спасибо.

S>А почему не:


S>
S>class Shop : IShop
S>{
S>    public void Sell(ISeller seller)
S>    {

S>    }
S>}
S>


S>Товары продавать должен все-таки магазин, но у каждого товара может быть своя специфика.


Как тогда выбрать нужного seller? Перед вызовом Sell проверять if'ами тип товара?
Извините не совсем понял идею.
Re: Вопрос по подходу к реализации паттерна стратегия c#
От: paradoks  
Дата: 09.12.19 09:00
Оценка:
Товары продает магазин.
Модель имхо такая

1) создаются объекты покупателей (с некоторой частотой)

2) объекты витрины посылают покупателям сигналы с описанием объектов товаров

3) в ответ покупатели посылают сигналы с запросами на получение товаров в некоторых кол-вах к витрине

4) обмен данными витрины и покупателей

5) обмен данными витрин и склада

6) покупатель обменивается данными с объектом касса

7) покупатель уходит из магазина (объект покупатель уничтожается и все объекты товары связанные с ним )

8) Объект Супервайзер-магазина создает и уничтожает объекты витрин по признакам нет товаров, нет методов продажи и тд. удаление из вирин просрочки
перемещет товары изсклада на итины итд. Супервайзер запрашивает инфу о методах продаж у объекта маркетолог

8) описание методов продаж всех товаров содержится в объекте маркетолог, там же дефолтные методы продаж для всех товаров в том числе которых нет
на складе и витринах.
Отредактировано 09.12.2019 9:06 paradoks . Предыдущая версия .
Re[3]: Вопрос по подходу к реализации паттерна стратегия c#
От: Cyberax Марс  
Дата: 09.12.19 09:08
Оценка:
Здравствуйте, corpse56, Вы писали:

C>>Если практический, то не используем никаких нафиг там стратегий, а пишем тупой код с if'ами для разных типов товаров. После того, как будут написаны (как минимум) продажи для 3 типов товаров, то смотрим, что можно объединить и абстрагировать.

C>Да вот нечто такое уже есть и хочется от if'ов избавиться. Но я ума не приложу как это сделать иначе, чем ссылку на логику продажи пихнуть в товар. То есть при создании товара создавать нужного seller'a и хранить его в товаре.
Ну значит, и не надо ничего менять. Пусть остаются if'ы — в них нет ничего плохого.

Можно, конечно, попробовать создать что-то типа "<xxx>Workflow", в который запихать методы продажи. В товары добавить идентификатор типа workflow, и делать диспетчеризацию в коде продажи.

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

C>Ведь неизвестно какой тип товара... Только если товар при создании создавал бы в себе нужный seller. А иначе придётся проверять тип товара if'ами?

Да, а что?
Sapienti sat!
Re[3]: Вопрос по подходу к реализации паттерна стратегия c#
От: Sharov Россия  
Дата: 09.12.19 10:09
Оценка:
Здравствуйте, corpse56, Вы писали:

C>Как тогда выбрать нужного seller? Перед вызовом Sell проверять if'ами тип товара?

C>Извините не совсем понял идею.

Согласен, что непонятоно. Я имел в виду следующее: товар не должен сам себя продавать, продавать его должен магазин. Взаимодействие магазина и товара тоже должно быть простым и прямолинейным. Т.е. тут, вероятно,
должна быть третья сущность, которая взяла бы на себя всю сложность бизнес логики и связывания IShop и ISell.
Кодом людям нужно помогать!
Re[2]: Вопрос по подходу к реализации паттерна стратегия c#
От: corpse56  
Дата: 09.12.19 12:25
Оценка:
Здравствуйте, Carc, Вы писали:

C>По моему тут не через паттерн "стратегия" нужно делать, а через паттерн "визитер".


Вот как получилось через паттерн визитёр. Можно запустить на dotnetfiddle
Интересно узнать у кого какое мнение на этот вариант.

using System;
using System.Collections.Generic;


namespace visitor_example
{
    abstract class baseClass
    {
        public abstract string AcceptSellVisitor(ISeller visitor);
        public abstract string AcceptReclamationVisitor(IReclamation visitor);
    }

    class A : baseClass
    {
        public string Name = "A";
        public override string AcceptSellVisitor(ISeller visitor)
        {
            return visitor.Sell(this);
        }
        public override string AcceptReclamationVisitor(IReclamation visitor)
        {
            return visitor.Reclamate(this);
        }
    }

    class B : baseClass
    {
       public string Name = "B";
       public override string AcceptSellVisitor(ISeller visitor)
        {
            return visitor.Sell(this);
        }
        public override string AcceptReclamationVisitor(IReclamation visitor)
        {
            return visitor.Reclamate(this);
        }
    }

    interface ISeller
    {
        string Sell(A item);
        string Sell(B item);
    }
     interface IReclamation
    {
        string Reclamate(A item);
        string Reclamate(B item);
    }
    class SellVisitor : ISeller
    {
        public string Sell(A item)
        {
            return "Sell A "+item.Name;
        }
        public string Sell(B item)
        {
            return "Sell B "+item.Name;
        }
    }
    class ReclamationVisitor : IReclamation
    {
        public string Reclamate(A item)
        {
            return "Reclamate A "+item.Name;
        }
        public string Reclamate(B item)
        {
            return "Reclamate B "+item.Name;
        }
    }
    class Shop
    {
            public SellVisitor sell = new SellVisitor();
            public ReclamationVisitor recl = new ReclamationVisitor();
    }
    public class Program
    {
        public static void Main()
        {
            Shop shop = new Shop();
            var list = new List<baseClass> { new A(), new B(), new A(), new A(), new B() };
            foreach (var item in list)
            {
                Console.WriteLine(item.AcceptSellVisitor(shop.sell));
                Console.WriteLine(item.AcceptReclamationVisitor(shop.recl));
            }
        }
    }
}



C>Или же заводить еще один интерфейс "покупка" (ну или "продажа"), который завязан на два других интерфейса. "Магазин" и "товар". Через параметры, или ссылки.

C>Явно же напрашивается третья сущность…

Тут я не совсем понял. Типа интерфейс "покупка" имеет метод, который принимает два интерфейса "магазин" и "товар"? А как тогда он будет определять как именно продавать? if'ами определить тип товара?

Спасибо.
Re[15]: Вопрос по подходу к реализации паттерна стратегия c#
От: Vladek Россия Github
Дата: 10.12.19 07:56
Оценка:
Здравствуйте, samius, Вы писали:

V>>Выяснить, какую роль играют поведение, состояние и идентичность объектов в ООП, не составляет никакого труда.

S>Я хотел выяснить немного другое. Что значит что поведение и состояние в ООП должны быть вместе и почему логику продажи в труООП надо совать в товар.

Гради Буч написал книгу, чтобы объяснить эти фундаментальные концепции. Читать надо, вот прямая цитата:

Объекты не существуют изолированно, а подвергаются воздействию или сами воздействуют на другие объекты.
Поведение — это то, как объект действует и реагирует; поведение выражается в терминах состояния объекта и передачи сообщений.
Иными словами, поведение объекта — это его наблюдаемая и проверяемая извне деятельность.
Операцией называется определенное воздействие одного объекта на другой с целью вызвать соответствующую реакцию. Например, клиент может активизировать операции append и pop для того, чтобы управлять объектом-очередью (добавить или изъять элемент). Существует также операция length, которая позволяет определить размер очереди, но не может изменить это значение. В чисто объектно-ориентированном языке, таком как Smalltalk, принято говорить о передаче сообщений между объектами. В языках типа C++, в которых четче ощущается процедурное прошлое, мы говорим, что один объект вызывает функцию-член другого. В основном понятие сообщение совпадает с понятием операции над объектами, хотя механизм передачи различен. Для наших целей эти два термина могут использоваться как синонимы.
В объектно-ориентированных языках операции, выполняемые над данным объектом, называются методами и входят в определение класса объекта. В C++ они называются функциями-членами. Мы будем использовать эти термины как синонимы.
Передача сообщений — это одна часть уравнения, задающего поведение. Из нашего определения следует, что состояние объекта также влияет на его поведение. Рассмотрим торговый автомат. Мы можем сделать выбор, но поведение автомата будет зависеть от его состояния. Если мы не опустили в него достаточную сумму, скорее всего ничего не произойдет. Если же денег достаточно, автомат выдаст нам желаемое (и тем самым изменит свое состояние). Итак, поведение объекта определяется выполняемыми над ним операциями и его состоянием, причем некоторые операции имеют побочное действие: они изменяют состояние. Концепция побочного действия позволяет уточнить наше определение состояния:
Состояние объекта представляет суммарный результат его поведения.
Наиболее интересны те объекты, состояние которых не статично: их состояние изменяется и запрашивается операциями.


Почему у класса List<T> есть метод Add? Это же я добавляю элемент в список, список сам себя не заполняет!!! У меня будет простой и понятный объект ListManager, у которого и будет набор методов для работы со списком. А список это всего лишь структура данных!

Спорить на фундаментальном уровне — заниматься бесполезным ликбезом для ленивых умов.
Re[16]: Вопрос по подходу к реализации паттерна стратегия c#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 10.12.19 11:47
Оценка: +1
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, samius, Вы писали:


V>>>Выяснить, какую роль играют поведение, состояние и идентичность объектов в ООП, не составляет никакого труда.

S>>Я хотел выяснить немного другое. Что значит что поведение и состояние в ООП должны быть вместе и почему логику продажи в труООП надо совать в товар.

V>Гради Буч написал книгу, чтобы объяснить эти фундаментальные концепции. Читать надо, вот прямая цитата:


V>

V>Объекты не существуют изолированно, а подвергаются воздействию или сами воздействуют на другие объекты.
V> Поведение — это то, как объект действует и реагирует; поведение выражается в терминах состояния объекта и передачи сообщений.
V> Иными словами, поведение объекта — это его наблюдаемая и проверяемая извне деятельность.
V> Операцией называется определенное воздействие одного объекта на другой с целью вызвать соответствующую реакцию. Например, клиент может активизировать операции append и pop для того, чтобы управлять объектом-очередью (добавить или изъять элемент). Существует также операция length, которая позволяет определить размер очереди, но не может изменить это значение. В чисто объектно-ориентированном языке, таком как Smalltalk, принято говорить о передаче сообщений между объектами. В языках типа C++, в которых четче ощущается процедурное прошлое, мы говорим, что один объект вызывает функцию-член другого. В основном понятие сообщение совпадает с понятием операции над объектами, хотя механизм передачи различен. Для наших целей эти два термина могут использоваться как синонимы.
V> В объектно-ориентированных языках операции, выполняемые над данным объектом, называются методами и входят в определение класса объекта. В C++ они называются функциями-членами. Мы будем использовать эти термины как синонимы.
V> Передача сообщений — это одна часть уравнения, задающего поведение. Из нашего определения следует, что состояние объекта также влияет на его поведение. Рассмотрим торговый автомат. Мы можем сделать выбор, но поведение автомата будет зависеть от его состояния. Если мы не опустили в него достаточную сумму, скорее всего ничего не произойдет. Если же денег достаточно, автомат выдаст нам желаемое (и тем самым изменит свое состояние). Итак, поведение объекта определяется выполняемыми над ним операциями и его состоянием, причем некоторые операции имеют побочное действие: они изменяют состояние. Концепция побочного действия позволяет уточнить наше определение состояния:
V> Состояние объекта представляет суммарный результат его поведения.
V> Наиболее интересны те объекты, состояние которых не статично: их состояние изменяется и запрашивается операциями.


V>Почему у класса List<T> есть метод Add? Это же я добавляю элемент в список, список сам себя не заполняет!!! У меня будет простой и понятный объект ListManager, у которого и будет набор методов для работы со списком. А список это всего лишь структура данных!


V>Спорить на фундаментальном уровне — заниматься бесполезным ликбезом для ленивых умов.


Спорить с Бучем здесь совершенно не о чем. Он предлагает соглашение — что именно называть поведением и операциями. Но совершенно не понятно откуда из процитированного следует что метод Sell должен быть у зубочистки, как поменяется состояние товара "зубочистка" при вызове этого метода.
Более того, в примере Буча рассмотрен торговый автомат, который меняет свое состояние. Но не упомянуты состояния товаров, которыми оперирует автомат. Странно, но процитированное не предполагает труООП-шности товара, проданного автоматом. Может быть надо читать дальше?
Re[17]: Вопрос по подходу к реализации паттерна стратегия c#
От: Vladek Россия Github
Дата: 11.12.19 09:37
Оценка: :)
Здравствуйте, samius, Вы писали:

S>Спорить с Бучем здесь совершенно не о чем. Он предлагает соглашение — что именно называть поведением и операциями. Но совершенно не понятно откуда из процитированного следует что метод Sell должен быть у зубочистки, как поменяется состояние товара "зубочистка" при вызове этого метода.


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

Товар Зубочистка при вызове метода Продать может как минимум уменьшить своё свойство Количество на единицу.

S>Более того, в примере Буча рассмотрен торговый автомат, который меняет свое состояние. Но не упомянуты состояния товаров, которыми оперирует автомат. Странно, но процитированное не предполагает труООП-шности товара, проданного автоматом. Может быть надо читать дальше?


Да, надо читать дальше — в книге есть примеры программ и описан процесс проектирования объектов.
Re[18]: Вопрос по подходу к реализации паттерна стратегия c#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 11.12.19 15:55
Оценка: 76 (1) +1
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, samius, Вы писали:


S>>Спорить с Бучем здесь совершенно не о чем. Он предлагает соглашение — что именно называть поведением и операциями. Но совершенно не понятно откуда из процитированного следует что метод Sell должен быть у зубочистки, как поменяется состояние товара "зубочистка" при вызове этого метода.


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

Я бы вывернул все наизнанку. Операции реализуются в виде методов не потому "что объекты сами меняют свое состояние (инкапсуляция)". Первичен контракт, или поведение системы (пусть системы объектов). Как там хранится состояние, как делится между объектами — дело вообще десятое. Например, может быть ОО фасад над абсолютно открытым набором данных (допустим, JSON). Т.е. пока есть контракт, пока он выполняется, никому нет дела до того, чье состояние меняет объект. И именно это есть инкапсуляция в широком смысле, как двойственное понятие барьеру абстракции, а не приписывание состояния объектам. А если шагнуть дальше — то есть примеры контрактов без состояния, следовательно без поведения. Контролировать проще.

V>Товар Зубочистка при вызове метода Продать может как минимум уменьшить своё свойство Количество на единицу.

Не лучшая идея — держать живое Количество в товаре. Им очень тяжело управлять, имея несколько товаров в чеке и конкуренцию за доступ к этому свойству каждого товара. Сразу начинает болеть голова от персистентности этого состояния, согласованности с другими данными (журнал продаж, поставок на склад и т.п.).
Вообще говоря, не вполне очевидно, почему свойство Количество приписано к товару Зубочистка. И почему оно должно уменьшаться именно на единицу при вызове метода Продать? Продать можно и зубочистки, которые не поставили на склад и даже не изготовили. Ну а почему нет?
А если у нас в зубочистке нет счетчика, то и обращаться к нему "ПродайСебя" вроде как смысла нет.

S>>Более того, в примере Буча рассмотрен торговый автомат, который меняет свое состояние. Но не упомянуты состояния товаров, которыми оперирует автомат. Странно, но процитированное не предполагает труООП-шности товара, проданного автоматом. Может быть надо читать дальше?


V>Да, надо читать дальше — в книге есть примеры программ и описан процесс проектирования объектов.

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