Спор шел о местонахождении функций в классе/хелпере.
Вы усложнили условия задачи:
А теперь представь, появилось новое бизнес требование . TaxRate теперь не свойство продукта, а вычисляется в зависимости от клиента (страна/штат и т.д, физическое лицо/юридическое лицо, и т.д.). Теперь какой подход лучше?
Я высказал мысль, что в этих обстоятельствах оба подхода потребуют одинаковых трудозатрат по изменению дизайна.
Я ошибочно предполагал, что вы остаетесь в рамках топика.
Оказалось, что вы начинали искать изначальные ошибки вымышленной модели вымышленного бизнеспроцесса на основании вымышленных вами изменений этого самого процесса.
И спрашиваете меня Ага>По существу есть что сказать?
Все что было у меня сказать по существу я сказал всем кто вел диалог по существу.
Заниматься вымышленным жизненным циклом вымышленного ПО предоставлю вам.
Здравствуйте, Ziaw, Вы писали:
Z>Оказалось, что вы начинали искать изначальные ошибки вымышленной модели вымышленного бизнеспроцесса на основании вымышленных вами изменений этого самого процесса.
Все зависимости от правдивости данного замечания, плюсмильён за сарказм. Я чрезвычайно хохотался.
Здравствуйте, AndrewVK, Вы писали:
AVK>>>Какой такой? G>>Когда экранные формы привязываются к объектам.
AVK>Функция редактирования в форме получает на вход экземепляр? Получает. Меняет состояние? Меняет. Значит, согласно твоему критерию: AVK>
Метод, который принимает x в качестве параметра и его действия заключаются в измененении x, я помещу в класс x.
AVK>метод редактирования объекта в UI должен быть помещен в класс, который редактируется.
Не передергивай. Такое решение быдет пристрелено раньше, чем дело дойдет до конкретных методов.
Стоит рассматривать более полную картину в таком случае.
Здравствуйте, gandjustas, Вы писали:
AVK>>Функция редактирования в форме получает на вход экземепляр? Получает. Меняет состояние? Меняет. Значит, согласно твоему критерию: AVK>>
Метод, который принимает x в качестве параметра и его действия заключаются в измененении x, я помещу в класс x.
AVK>>метод редактирования объекта в UI должен быть помещен в класс, который редактируется. G>Не передергивай.
А я и не передергиваю. Я тебе задал конкретный вопрос, на который ты уже третье сообщение никак не можешь ответить.
G> Такое решение быдет пристрелено раньше, чем дело дойдет до конкретных методов.
Почему? Какое будет не пристрелено?
G>Стоит рассматривать более полную картину в таком случае.
Картина достаточно полная. Простейшая задача — есть класс, его нужно редактировать в UI. Точка. Для простоты можешь считать, что это и есть все приложение.
... << RSDN@Home 1.2.0 alpha 4 rev. 1095 on Windows Vista 6.0.6001.65536>>
Здравствуйте, AndrewVK, Вы писали:
G>>Стоит рассматривать более полную картину в таком случае. AVK>Картина достаточно полная. Простейшая задача — есть класс, его нужно редактировать в UI. Точка. Для простоты можешь считать, что это и есть все приложение.
Здравствуйте, stump, Вы писали:
S>Вообще-то сумма по заказу это свойство заказа, не зависимо от чего зависит расчет этой суммы, где расположен метод, который ее считает. и вообще считается она или хранится в где нибудь.
Очень интересная мысль. Которая, позволяет сделать кое-какие выводы (ИМХО):
Сумма заказа — свойство заказа (с этим очень трудно поспорить)
А вот Алгоритм расчета стоимости заказа, явно уже не отностится к отвественности абстракции "Заказ"
По этому получается такая вот загагулина:
Это гуд:
public class Order
{
public IList<OrederLine> OrderLines {get;set;}
public decimal Total{get;set;}
}
///Может быть Хелпером либо Иньекциейpublic class OrderTotalCalculator
{
public decimal UpdateTotal(Order order){}
}
Это не гуд:
public class Order
{
public IList<OrederLine> OrderLines {get;set;}
public decimal GetTotal()
{
//get totals from order lines
}
}
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, C...R...a...S...H, Вы писали:
CRA>> public decimal UpdateTotal(Order order){}
AVK>Лучше все же CalcTotal,а не UpdateTotal.
Думаю, что давать имя CalcTotal, следует в случае IoC
В случае же хелпера в после подходит UpdateTotal, только возвращать он должен void конечно.
Здравствуйте, C...R...a...S...H, Вы писали:
CRA>В случае же хелпера в после подходит UpdateTotal, только возвращать он должен void конечно.
Вот как раз я и хотел обратить внимание на то, что лучше бы этот метод ничего сам не менял, потому что это более универсальное решение. К примеру, сумму может быть нужно рассчитать предварительно, без изменения персистентного класса.
... << RSDN@Home 1.2.0 alpha 4 rev. 1095 on Windows Vista 6.0.6001.65536>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Вот как раз я и хотел обратить внимание на то, что лучше бы этот метод ничего сам не менял, потому что это более универсальное решение. К примеру, сумму может быть нужно рассчитать предварительно, без изменения персистентного класса.
Универсальное решение — это очень и очень хорошо, но часные случаи, все же имею правно на существование.
Так что оба решения, могут существовать, но выбор правильного решения можно сделать только в определенном контексте.
Здравствуйте, C...R...a...S...H, Вы писали:
CRA>Универсальное решение — это очень и очень хорошо, но часные случаи, все же имею правно на существование.
Имеют, если дают какое то существенное преимущество. Здесь же я никаких преимуществ не вижу, зато недостатки ввиде скрытого изменения состояния в наличии.
... << RSDN@Home 1.2.0 alpha 4 rev. 1095 on Windows Vista 6.0.6001.65536>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Имеют, если дают какое то существенное преимущество. Здесь же я никаких преимуществ не вижу, зато недостатки ввиде скрытого изменения состояния в наличии.
Интересно, где вы видите скрытое изенение состояни?
В сигнатуре метода четко все прописано:
CRA>// ...
CRA>// Может быть Хелпером либо Иньекцией
CRA>//...
CRA>
Это очень хорошо, но тема "Куда же деть саму функцию (а не реализацию алгоритма)" не раскрыта
Вернее это пример того за что "сражается" stump: функция находится в самом классе (а реализация где-то еще).
Здравствуйте, AndrewVK, Вы писали:
AVK>Тем не менее преимуществ у такого варианта я так и не увидел.
Странно Андрей, как можно делать такие вывод в отрыве от контекста проблемы.
Давайте попробуем разобрать преимущества и недостатки обоих методов, для того, что бы не переругаться и найти компромисс:
Универсальное решение:
Позволяет клиенту полностью контролировать изменение Total, но в тоже время нагружает клиента лишней ответственностью.
Думаю тут спорить нет смысла, так как это общеизвестная зависимость
Частный случай:
Абстрагирует клиента, и избавляет его от ответственности (лишней или нет, зависти от задачи), при этом не дает возможность контролировать процесс изменения Total.
Итог:
В зависимости от задачи, мы можем принять решение:
Либо разрешаем клиенту вмешиваться в процесс изменения Total, добавляя ему доп. забот, либо упрощаем клиенту работу, используя абстракцию.
Конкретное, решение я еще раз повторю, можно принять только в конкретной ситуации, баталии на примере сферического коня в вакууме, смысла особого не имеют, я думаю, все со мной согласятся.
Здравствуйте, C...R...a...S...H, Вы писали:
CRA>Странно Андрей, как можно делать такие вывод в отрыве от контекста проблемы.
ИМХО контекста тут предостаточно, чтобы ответить на заданный мной вопрос.
CRA>Универсальное решение: CRA>Позволяет клиенту полностью контролировать изменение Total, но в тоже время нагружает клиента лишней ответственностью.
Какой ответственностью? Присвоением значения свойству? Не нагружает оно, наоборот — эта ответственность переносится в тот кусок кода, который предназначен для изменения заказа, а не нагружает метод для вычисления суммы еще и ответственностью за присвоение значения. Тот самый затюканый здесь SRP на уровне метода.
Если же нам нужно абстрагировать клиента от процесса изменений (заметь, до этого нигде о необходимости подобной абстракции никто не говорил), нужно заводить отдельный метод — Update, который, в свою очередь, будет вызывать метод Calc. Главное — метод Calc не должен ничего сам менять.
... << RSDN@Home 1.2.0 alpha 4 rev. 1095 on Windows Vista 6.0.6001.65536>>
A>Это очень хорошо, но тема "Куда же деть саму функцию (а не реализацию алгоритма)" не раскрыта
Да ладно, не раскрыта
В конкретном примере "Order", после поста Stump от 23.07.08 15:20
Все стало прозрачно (для меня точно):
Заказ может содержать свойство Total, так как данное свойство находится в зоне его ответственности, НО заказ не может содержать метод расчета Total, так как это уже совершенно другая ответственность. Поэтому смысл применения правила, которое озвучил IB, в этом примере отсутствует, так как принцип SRP не позволяет нам «нагрузить» заказ и ответственность за содержание OrderLine и добавить ответственность за выполнение расчетов над OrderLine, думаю, что и IB и Stump со мной согласятся.
CRA>НО заказ не может содержать метод расчета Total, так как это уже совершенно другая ответственность.
Не может, но может сам инициировать пересчет, т.е. фактически содержать метод расчета (но не алгоритм).
A>Не может, но может сам инициировать пересчет, т.е. фактически содержать метод расчета (но не алгоритм).
Т.е. юзер класса может даже не знать, что для подсчета Total используется некий другой класс, а не сам Order.
Здравствуйте, AndrewVK, Вы писали:
AVK>ИМХО контекста тут предостаточно, чтобы ответить на заданный мной вопрос.
Видимо, Вы обладаете очень интересным скилом – телепатией
Но, возможно вы могли упустить из вида, одно маленькое требование в одном из контекстов, которое звучит так:
Клиент не имеет право изменять Total напрямую, а может использовать только специально предоставленные ему механизмы.
AVK>Какой ответственностью? Присвоением значения свойству? Не нагружает оно, наоборот — эта ответственность переносится в тот кусок кода, который предназначен для изменения заказа,
Андрей, вы пытаетесь выполнить подмену понятий:
Пытаетесь уменьшить значимость сказанных мною слов, приравнивая их к совершенно другому понятию.
В данном конкретном случае, вы сделали так: ответственность == присвоение значения свойству, но это не так, ответственность есть ответственность, присвоение значения свойству – есть то как эта ответственность реализуется в коде.
AVK>а не нагружает метод для вычисления суммы еще и ответственностью за присвоение значения. Тот самый затюканый здесь SRP на уровне метода.
Применять SRP на уровне метода — это очень и очень проблематично, так как можно скатиться до применения SRP для каждого оператора, так что считаю обсуждение SRP для каждого метода бредовой идеей, и вы я думаю со мой согласитесь (ведь не будете же вы утверждать, что обработка исключений и вызов метода Х в методе Y нарушает SRP для метода Y)
AVK>Если же нам нужно абстрагировать клиента от процесса изменений (заметь, до этого нигде о необходимости подобной абстракции никто не говорил)
Видимо вы додумали задачу, до конца сделав все возможные предположения за меня. Я же пытаюсь сообщить вам, что конкретные необходимости не известны даже мне AVK>нужно заводить отдельный метод — Update, который, в свою очередь, будет вызывать метод Calc. Главное — метод Calc не должен ничего сам менять.
Я хочу обратить внимание, на один факт: Вы сделали предположение о том, что у меня написано в методе UpdateTotal, при этом предположение это вы сделали в удобном для себя разрезе.
Вы посчитали что в моем объекте нет метод Calc, я вам хочу сообщить, так как пример мой, то метод Calc там есть, и он сделан приватным, а вот почему он сделан приватным вы можете увидит в начале поста.