Здравствуйте, Gajdalager, Вы писали:
T>>Дык в том-то и дело, что полиморфизма без методов — нет, а вы ж ратуете за их отсутствие в сущностях.
G>О терминах спорить будем или согласимся, что идется только о runtime-полиморфизме в ОО-языках? http://en.wikipedia.org/wiki/Type_polymorphism
Да, имелся именно runtime-полиморфизм. Кстати, тремя сообщениями выше я упоминал про наследование,так что при желании можно было понять, что именно я имел в виду. Тем не менее, прошу прощения, если кого-то ввел в заблуждение.
T>>>Кукую? IB>>Про полиморфизм тебе уже рассказали.
T>Дык в том-то и дело, что полиморфизма без методов — нет, а вы ж ратуете за их отсутствие в сущностях.
Здравствуйте, Tissot, Вы писали:
T>Понятие сложности — вопрос сугубо субъективный, никто тебе формулы для вычисления сложности не даст, придется с этим смириться.
Как раз понятие сложности сущесвует объективно, а вот привычность (которую многие путают с удобством) — субъективно.
Формула для вычисления сложности есть. Mantainability Index называется.
Но есть недостатки такой метрики. Во-первых она работает только для всего проекта. Расчет индекса для маленькой части большого приложения ничего не показывает. Во-вторых индекс хреново работает для не ОО-языков.
Здравствуйте, VGn, Вы писали:
T>>Дык в том-то и дело, что полиморфизма без методов — нет, а вы ж ратуете за их отсутствие в сущностях.
VGn>Разъясните мне-идиоту зачем полиморфизм данным?
Данным, он наверное не нужен, а объектам domain model — вполне.
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, Tissot, Вы писали:
T>>Понятие сложности — вопрос сугубо субъективный, никто тебе формулы для вычисления сложности не даст, придется с этим смириться. G>Как раз понятие сложности сущесвует объективно, а вот привычность (которую многие путают с удобством) — субъективно. G>Формула для вычисления сложности есть. Mantainability Index называется.
Не верю я в такие индексы. Та же Cyclomatic Complexity несложными манипуляциями с кодом уменьшается до требуемых показателей. Зачастую не надо даже разбираться, что код делает. Туфта все это.
Здравствуйте, mogadanez, Вы писали:
M>маленько офтоп, но всеже — как то на форуме преобладает позиция втоптать чужое мнение чем продемонстрировать свое.
+1, но с небольшой поправочкой. Зачастую пытаются втоптать не мнение, а собеседника.
Здравствуйте, gandjustas, Вы писали:
T>>Если ты внимательнее посмотришь validation app block, то увидишь, что в нем предусмотрен вариант для тех случаев, когда сущность сама себя валидирует. G>Всегда все можно сделать неправильно, и оно при этом даже будет работать.
Если подсистему валидации нормально продизанить, то получится что-то вроде validation app block.
Так все-таки "нормально" или "неправильно"?
T>>>>А данные — это набор атрибутов, следовательно обязанность "хранить данные" — это составная обязанность, которая может быть разбита на более мелкие. G>>>Это уже плод больного воображения. T>>Нет, это всего лишь SRP доведенный до конца. G>Это бред.
Это иллюстрация того, что фанатизм до хорошего не доводит.
G>>>Ага, самоя хорошая мера называется SRP. T>>См. выше. G>С каких пор абсурдные высказывания являются аргументом?
Есть такой подход в математике — доказательство от противного.
G>SRP придумали не для того чтобы начинающих программистов пугать.
Знание SRP не отменяет необходимости наличия головы не плечах.
G>>>На моей первой работе был гениальный класс Queue (очередь), унаследованный от TStringList (на делфи). Содатели этого класса мотивировали удобством, хотя через интерфейс TStringList можно было нарушить работу класса очереди. T>>Неудачный пример. G>Почему? Удобно же.
Применим тот же самый метод повторно: вы вроде как говорили, что не следует смешивать данные и методы работы с ними. Означает ли это, что вы, следуя SRP спроектировали бы класс queue примерно так:
public Queue {
public object[] Data;
}
а для изменения queue у вас есть специальный сервисный класс
public QueueService {
public void Enqueue(Queue data, object obj) {
}
public object Dequeue(Queue data) {
}
}
Здравствуйте, Tissot, Вы писали: T>Сама реализация валидации может быть расположена и где-то вовне класса, а класс может просто делегировать вызов. Очень удобно, например на SubmitChanges проверять таким образом валидность измененных сущностей.
Эта схема хорошо работает только для одного вырожденного случая: когда пользователь интерактивно меняет какие-то свойства каких-то объектов.
Вот тут да, всё правильно. И валидация в объектах — самое оно, и Unit of Work к месту. И даже оптимистическая блокировка более-менее работает.
Потому, что позволяют генерировать UI в полуавтоматическом режиме, и при этом ничего существенно более полезного всё равно придумать нельзя — упираешься в произвольность пользовательских действий.
Обобщать этот подход на все остальные случаи — ошибка.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
T>>Сама реализация валидации может быть расположена и где-то вовне класса, а класс может просто делегировать вызов. Очень удобно, например на SubmitChanges проверять таким образом валидность измененных сущностей. S>Эта схема хорошо работает только для одного вырожденного случая: когда пользователь интерактивно меняет какие-то свойства каких-то объектов. S>Вот тут да, всё правильно. И валидация в объектах — самое оно, и Unit of Work к месту. И даже оптимистическая блокировка более-менее работает. S>Потому, что позволяют генерировать UI в полуавтоматическом режиме, и при этом ничего существенно более полезного всё равно придумать нельзя — упираешься в произвольность пользовательских действий.
Ну наконец-то.
S>Обобщать этот подход на все остальные случаи — ошибка.
Я не считаю, что это такой уж вырожденный случай для корпоративных приложений. В них практически всегда присутствует интерактивное изменение свойств объектов.
Здравствуйте, Tissot, Вы писали: T>Я не считаю, что это такой уж вырожденный случай для корпоративных приложений. В них практически всегда присутствует интерактивное изменение свойств объектов.
Вопрос сложный. Конечно, везде есть какое-то редактирование справочников.
Но с дальнейшим ростом аппетитов оказывается, что ввод данных стоит в самом начале длинной цепочки. Грубо говоря, логика комплектования заказа по складам и группировки заказов для оптимальной доставки получается значительно тяжелее, чем вся форма ввода заказа и свойств контрагента.
Вот тут-то у архитектора и наступает просветление. То, что вначале казалось таким приятным и удобным, теперь висит тяжелым грузом и сдерживает дальнейшее наращивание бизнес-логики, а также масштабирование системы.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Tissot, Вы писали:
T>Здравствуйте, VGn, Вы писали:
T>>>Дык в том-то и дело, что полиморфизма без методов — нет, а вы ж ратуете за их отсутствие в сущностях.
VGn>>Разъясните мне-идиоту зачем полиморфизм данным?
T>Данным, он наверное не нужен, а объектам domain model — вполне.
Здравствуйте, Tissot, Вы писали:
T>Здравствуйте, gandjustas, Вы писали:
G>>Здравствуйте, Tissot, Вы писали:
T>>>Понятие сложности — вопрос сугубо субъективный, никто тебе формулы для вычисления сложности не даст, придется с этим смириться. G>>Как раз понятие сложности сущесвует объективно, а вот привычность (которую многие путают с удобством) — субъективно. G>>Формула для вычисления сложности есть. Mantainability Index называется.
T>Не верю я в такие индексы. Та же Cyclomatic Complexity несложными манипуляциями с кодом уменьшается до требуемых показателей. Зачастую не надо даже разбираться, что код делает. Туфта все это.
Пример в студию.
Cyclomatic Complexity очень сильно чувствуешь на своей ж*** когда занимаешься whitebox-тестированием.
Очень даже объективный показатель, который работает для любых языков. И полипорфизм, за который вы тут так боретесь — именно средство уменьшения Cyclomatic Complexity.
Здравствуйте, Tissot, Вы писали:
T>Здравствуйте, gandjustas, Вы писали:
T>>>Если ты внимательнее посмотришь validation app block, то увидишь, что в нем предусмотрен вариант для тех случаев, когда сущность сама себя валидирует. G>>Всегда все можно сделать неправильно, и оно при этом даже будет работать.
T>
T>Если подсистему валидации нормально продизанить, то получится что-то вроде validation app block.
T>Так все-таки "нормально" или "неправильно"?
Нормально. Любая библиотека должна предоставлять множество возможностей, но какими стоит пользоваться, а какими — нет уже вам решать.
T>>>>>А данные — это набор атрибутов, следовательно обязанность "хранить данные" — это составная обязанность, которая может быть разбита на более мелкие. G>>>>Это уже плод больного воображения. T>>>Нет, это всего лишь SRP доведенный до конца. G>>Это бред. T>Это иллюстрация того, что фанатизм до хорошего не доводит.
Это иллюстрация вашего непонимания SRP.
G>>>>На моей первой работе был гениальный класс Queue (очередь), унаследованный от TStringList (на делфи). Содатели этого класса мотивировали удобством, хотя через интерфейс TStringList можно было нарушить работу класса очереди. T>>>Неудачный пример. G>>Почему? Удобно же.
T>Применим тот же самый метод повторно: вы вроде как говорили, что не следует смешивать данные и методы работы с ними. Означает ли это, что вы, следуя SRP спроектировали бы класс queue примерно так: T>
T>public Queue {
T> public object[] Data;
T>}
T>
T>а для изменения queue у вас есть специальный сервисный класс T>
Не-а. В таком коде класс Queue не нужен, тем более он нарушет бредовый. Класс QueueService переименовываем в Queue, оставляем пару методов Enqueue, Dequeue и еще Count и всю реализацию прячим внутри Queue. И получаем нормальную очередь.
Здравствуйте, gandjustas, Вы писали:
VGn>>>Разъясните мне-идиоту зачем полиморфизм данным?
T>>Данным, он наверное не нужен, а объектам domain model — вполне.
G>domain model не содержит данных?
Содержит, но это не голые данные, а именно domain model
Здравствуйте, gandjustas, Вы писали:
G>Пример в студию.
Легко. Одна и величин, на которой основывается компексити — это кол-во if-ов. Часто бывает такой код выглядит так:
if (condition1())
action1();
else if (condition2())
action2();
...
else if (conditionN())
actionN();
Этот код тупо заменяется на словарь, где ключ — функция вычисляющая предикат, а в кач-ве значения — действие, которой надо выполнить, если предикат вернул true. И все, N ветвлений ушло.
Но это конечно простой случай, но к нему вполне можно свести многие ему подобные.
G>Cyclomatic Complexity очень сильно чувствуешь на своей ж*** когда занимаешься whitebox-тестированием. G>Очень даже объективный показатель, который работает для любых языков. И полипорфизм, за который вы тут так боретесь — именно средство уменьшения Cyclomatic Complexity.
Здравствуйте, Tissot, Вы писали:
T>Здравствуйте, gandjustas, Вы писали:
VGn>>>>Разъясните мне-идиоту зачем полиморфизм данным?
T>>>Данным, он наверное не нужен, а объектам domain model — вполне.
G>>domain model не содержит данных?
T>Содержит, но это не голые данные, а именно domain model
А что такое domain model? Интересует суть, а не цитаты из фаулера
Здравствуйте, gandjustas, Вы писали:
T>>Так все-таки "нормально" или "неправильно"? G>Нормально. Любая библиотека должна предоставлять множество возможностей, но какими стоит пользоваться, а какими — нет уже вам решать.
Слив засчитан.
T>>Это иллюстрация того, что фанатизм до хорошего не доводит. G>Это иллюстрация вашего непонимания SRP.
Обоснуй. Почему обязанность "хранить данные" не может быть разбита на более мелкие?
Только пожалуйста без аппелирования к тупости и необразованности своего собеседника. Спасибо.
T>>Применим тот же самый метод повторно: вы вроде как говорили, что не следует смешивать данные и методы работы с ними. Означает ли это, что вы, следуя SRP спроектировали бы класс queue примерно так: T>>
T>>public Queue {
T>> public object[] Data;
T>>}
T>>
T>>а для изменения queue у вас есть специальный сервисный класс T>>
G>Не-а. В таком коде класс Queue не нужен, тем более он нарушет бредовый. Класс QueueService переименовываем в Queue, оставляем пару методов Enqueue, Dequeue и еще Count и всю реализацию прячим внутри Queue. И получаем нормальную очередь.
Почему не нужен? Хранить данные — это ведь отдельная обязанность (с) gandjustas. Непоследовательно как-то получается.
Здравствуйте, gandjustas, Вы писали:
T>>Содержит, но это не голые данные, а именно domain model
G>А что такое domain model? Интересует суть, а не цитаты из фаулера
domain model — это программное представление концепций предметной области, максимально к ней (области) приближенное.
Здравствуйте, Tissot, Вы писали:
T>Здравствуйте, gandjustas, Вы писали:
G>>Пример в студию.
T>Легко. Одна и величин, на которой основывается компексити — это кол-во if-ов. Часто бывает такой код выглядит так: T>
T>if (condition1())
T> action1();
T>else if (condition2())
T> action2();
T>...
T>else if (conditionN())
T> actionN();
T>
T>Этот код тупо заменяется на словарь, где ключ — функция вычисляющая предикат, а в кач-ве значения — действие, которой надо выполнить, если предикат вернул true. И все, N ветвлений ушло.
Cyclomatic Complexity — это не количество ифов, а количество decision points, если у вас один if в цикле, то Cyclomatic Complexity такого куска равно количпеству проходов цикла.
Разница Cyclomatic Complexity видна когда занимаетесь тестированием кода.
T>Но это конечно простой случай, но к нему вполне можно свести многие ему подобные.
Такой код чаще всего получается при изначально плохом дизайне.
G>>Cyclomatic Complexity очень сильно чувствуешь на своей ж*** когда занимаешься whitebox-тестированием. G>>Очень даже объективный показатель, который работает для любых языков. И полипорфизм, за который вы тут так боретесь — именно средство уменьшения Cyclomatic Complexity.
T>Не единственное средство.
Я и не говорил что единственное.
Здравствуйте, Tissot, Вы писали:
T>Здравствуйте, gandjustas, Вы писали:
T>>>Так все-таки "нормально" или "неправильно"? G>>Нормально. Любая библиотека должна предоставлять множество возможностей, но какими стоит пользоваться, а какими — нет уже вам решать.
T>Слив засчитан.
Ну это к MS.
T>>>Это иллюстрация того, что фанатизм до хорошего не доводит. G>>Это иллюстрация вашего непонимания SRP.
T>Обоснуй. Почему обязанность "хранить данные" не может быть разбита на более мелкие? T>Только пожалуйста без аппелирования к тупости и необразованности своего собеседника. Спасибо.
Сначала "от протвного". Если следовать вашему пониманию SRP, то любой класс, содержащий более одного публичного члена нарушает SRP.
Но SRP был придуман не идиотами и не прижился бы будь он настолько абсурден.
В исходном определении SRP "обязанность" модуля приравнивается к необходимости изменять модуль. Например необходимость менять класс сущности возникает только при изменении схемы данных, поэтому он не нарушает SRP. Если мы в тотже класс засунем бизнес-логику и валидацию, то уже появится три причины менять класс: изменение данных, изменение бизнес-логики, изменение валидации, поэтому будет нарушение SRP.
Такой принцип не точен математически, но общую картину позволяет получить.
T>>>Применим тот же самый метод повторно: вы вроде как говорили, что не следует смешивать данные и методы работы с ними. Означает ли это, что вы, следуя SRP спроектировали бы класс queue примерно так: T>>>
T>>>public Queue {
T>>> public object[] Data;
T>>>}
T>>>
T>>>а для изменения queue у вас есть специальный сервисный класс T>>>
G>>Не-а. В таком коде класс Queue не нужен, тем более он нарушет бредовый. Класс QueueService переименовываем в Queue, оставляем пару методов Enqueue, Dequeue и еще Count и всю реализацию прячим внутри Queue. И получаем нормальную очередь.
T>Почему не нужен? Хранить данные — это ведь отдельная обязанность (с) gandjustas. Непоследовательно как-то получается.
"очередь" — это и есть одна обязанность класса. Для того чтобы быть полноценной очередью необходимо (и достаточно) реализиовать несколько членов, соотвествующих определенному контракту.