AVK>Религия мешает?
Ну вообще-то я не планировал открывать наружу ISynchronizedSet, а использовал его как internal проводник private поля.
Хотя смысл открыть наружу его есть, только тогда придется вылавливать ошибки там, где люди написали:
ISet s = new SynchronizedSet();
s.AddAll(collection);
В принципе для таких случаев можно придумать экзамен, пусть 100 раз на доске напишут.
Если мне нужна синхронизация при вызове AddAll я всегда буду строго указывать тип ISynchronizedSet.
Z>>Ужас он не от того, что мне пришлось это сделать, а от того, что я понимаю, что еще пара вариантов реализации AddAll и мне придется признаться, что мой дизайн унылое г.
AVK>Неа, унылое гавно, это когда в уже существующих методах вдруг появляется блокировка. Ну а главное — тема сис... вынесения методов не раскрыта. Где здесь преимущество варианта, когда твои AddAll находятся в ISet?
Меня тут просто замучали тыкать в факт того, что появиться может что угодно и где угодно!
При этом упирая на то, что вынос методов служит как раз облегчения расширения в таких ситуациях.
Как только этот факт перестал работать вашу пользу — его сразу списали в канализацию.
Здравствуйте, AndrewVK, Вы писали:
AVK>Ну а главное — тема сис... вынесения методов не раскрыта. Где здесь преимущество варианта, когда твои AddAll находятся в ISet?
Тут как раз просто, я его могу переопределить в классе SynchronizedSet.
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, Юрий Жмеренецкий, Вы писали:
A>>>Давай поставим вопрос ребром, зачем ты вообще решил увеличивать инкапуляцию? Ради упрощения поддержки? ЮЖ>>Т.е. результативнее снизить количество необходимых изменений, а не улучшать их "удобство". Как минимум, уменьшается объем потенциально возможных ошибок, набор тестов, да и просто количество необходимого времени.
A>Верно, но не про нас. То где находится метод: в классе или хелпере, никак не влияет ни на возможность его тестировать, ни на возможность его поменять или добавить новый метод. Прсото взяли и для себя упорядочили. Подчёркиваю, для себя. Другим эта упорядоченность на фиг не упала.
Еще как упала. Раз уж была упомянута STL: хороший пример — разделение алгоритмов и контейнеров: все что необходимо, так это предоставить пару итераторов — все остальное начнет работать автоматически. То же и для алгоритмов поверх любых контейнеров. А что будет если слить все в кучу ?
ЮЖ>>один класс должен иметь только одну причину для изменения. A>Утверждение, которое можно трактовать как угодно.
Отнюдь, трактовка ровно одна: один класс — одна причина для изменений.
Вот AndrewVK рядом(не знаю как ссылки на конкретные сообщения из плоского веб-интерфейса вставлять) про реструктуризатор писал:
Тем не менее, если хоть немного включить голову, то понятно, что алгоритмы сравнения схем нужно вынести в отдельный класс, занимающийся сравнением, код, который непосредственно модифицирует базу — в отдельный класс, куча методов сравнения элементов схемы из классов схемы в хелпер, код загрузки схем из БД и ресурсов — тоже должны быть отдельными классами и т.п.
Здесь множество причин для изменений. Я про это.
ЮЖ>>А вот снижение количества изменений, снижение количества потенциально возможных багов порожденных этими изменениями, снижение объемов тестирования, уменьшение времени, затраченного на эти изменения, увеличиние скорости реализации новых фич и т.п., — все это тоже в конечном итоге средства снижения стоимости и увеличения конкурентноспособности.
A>ОК, как вынос метода в хелпеер на это влияет? А? Не изменение архитектуры, а просто взяли и сделали второй класс и вытащили туда всё чему достаточно публичного контракта.
При необходимости изменения кода находящегося с хелпере — будет изменен только код в нем, место внесения изменений локализовано, и что самое главное: это изменение не затрагивает сам класс.
ЮЖ>>Повторному использованию, имхо, очень часто мешают лишние ответственности. A>Опять не в тему. Библиотека не стала делать больше или меньше, просто методы перераскидали по классам.
Тогда зачем вообще раскидывать? — один класс на библиотеку, да и не мучиться...
ЮЖ>>А такой код(библиотечный) тем более должен стремится к применению SRP по максимуму. Если я хочу от библиотеки 'A', то она и должна мне предоставить 'A', а не ['A' + 'B' + на всякий случай 'C' для удобства] в одном флаконе. Это просто снижает повторное использование(вместе с окупаемостью).
A>Опять не в тему. Библиотека не стала делать больше или меньше, просто методы перераскидали по классам.
Из нескольких классов, которые можно использовать независимо, проще собирать то что необходимо.
ЮЖ>>Можно пойти еще дальше и оставить только два итератора, плюс сделать строку иммутабельной и добавить string builder. A>И получить STL где у сттроки нет нормального find
А нормальный это какой ? с регэкспами и поиском через гугл?
A>И каждый пишет свой.
Может быть. В зависимости от задачи. Со строками проблема в том, что там слишком много потенциально настраиваемых моментов, и при попытке свалить все в кучу получится вышеупомянутый реструктуризатор.
A>Не надо SRP доводить до маразма стимулирую написание велосипедов.
Не надо доводить до маразма кажущееся "удобство" в виде автокомплита. Иначе чем объяснить изначальное существование в классе методов которых там не должно быть?
ЮЖ>>Т.е. автокомплит, если я правильно понял всю ветку — это и есть удобство? A>Конечно, автокомплит увеличивает производительность. Кто бы спорил.
Увеличивает производительность чего ? навигации по толстым классам ? Сначала сделали себе проблему, а потом ее же и решаем =)
Ничего против автокомплита не имею, но неужели это действительно может рассматриваться как критерий выбора библиотеки ?
Здравствуйте, Ziaw, Вы писали:
Z>Тут как раз просто, я его могу переопределить в классе SynchronizedSet.
И чем это лучше AddAllSync? А что, если для одной и той же коллекции нужен и с блокировкой доступ и без онной (как минимум в конструкторе с сигнатурой (IEnumerable<T>) блокировка не нужна)? Вводить специальное свойство еще — IsLockActive? Как думаешь, почему в ICollection есть свойства IsSynchronized и SyncRoot, а в ICollection<T> уже ничего подобного нет? Почему близкий по семантике твоему примеру метод Union находится в хелпере, а не в интерфейсе IEnumerable<T>? Это все ошибки дизайна? Какие из методов класса Enumerable по твоему должны находиться в интефейсе IEnumerable<T> и почему? А какие не должны и почему?
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Ziaw, Вы писали:
Z>>Ну вообще-то я не планировал открывать наружу ISynchronizedSet AVK>Ну начинается.
Что начинается? Не открою плохо, открою еще хуже.
Z>>Меня тут просто замучали тыкать в факт того, что появиться может что угодно и где угодно! AVK>Увы, но это действительно непреложый факт. Z>>При этом упирая на то, что вынос методов служит как раз облегчения расширения в таких ситуациях. AVK>Ага.
Так вот вполне реалистичная ситуация когда появившееся требование ложится на дизайн с вынесенным методом гораздо хуже чем на экземплярный.
Z>>Как только этот факт перестал работать вашу пользу — его сразу списали в канализацию. AVK>Кого списали в канализацию? Я лично никого в канализацию не списывал.
А как же это? AVK>Неа, унылое гавно, это когда в уже существующих методах вдруг появляется блокировка
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Ziaw, Вы писали:
Z>>Тут как раз просто, я его могу переопределить в классе SynchronizedSet. AVK>И чем это лучше AddAllSync?
Лучше тем, что передав экземпляр SynchronizedSet активно исползующийся в другом треде в любой метод с принимающий ISet я не буду гадать, будет там вызван AddAll или нет.
AVK>А что, если для одной и той же коллекции нужен и с блокировкой доступ и без онной (как минимум в конструкторе с сигнатурой (IEnumerable<T>) блокировка не нужна)? Вводить специальное свойство еще — IsLockActive?
В чьем конструкторе?
AVK>Как думаешь, почему в ICollection есть свойства IsSynchronized и SyncRoot, а в ICollection<T> уже ничего подобного нет?
Почему? Мне правда интересно.
AVK>Почему близкий по семантике твоему примеру метод Union находится в хелпере, а не в интерфейсе IEnumerable<T>?
Как минимум по причине обратной совместимости.
AVK>Это все ошибки дизайна? Какие из методов класса Enumerable по твоему должны находиться в интефейсе IEnumerable<T> и почему? А какие не должны и почему?
Я не выдумывал правил по выносу, я только показал, что правило выдуманное IB для улучшения расширяемости может сработать с точностью до наоборот.
Здравствуйте, Ziaw, Вы писали:
Z>Здравствуйте, AndrewVK, Вы писали:
AVK>>Здравствуйте, Ziaw, Вы писали:
Z>>>Какой мне предпочесть опираясь на OCP или другие соображения?
AVK>>
Z>Отлично, я быстренько все это пишу. Отдаю библиотеку все используют — все в восторге. Z>Однако через год обнаруживается, что в многопоточных приложениях ее использовать нельзя, т.к. отсутствует потокобезопасный тип множества.
Обычно на это сразу внимание обращают.
Кстати, раз вопрос коснусля блокировок: внутренняя блокировка в контейнере — вещь практически бесполезная. Блокировка контейнеров должна быть внешней. Вот скажем мне нужно за одну блокировку вызвать три раза AddAll для разных источников...
Здравствуйте, Ziaw, Вы писали:
Z>>>Ну вообще-то я не планировал открывать наружу ISynchronizedSet AVK>>Ну начинается. Z>Что начинается?
Начинается изменение задачи на ходу. Т.е. требовать в примере с Substring абсолютной конкретики можно, а тут вдруг задача с каждым сообщением меняется произвольным образом. Если хочешь конкретики — то твое решение никуда не годится, прозрачное и закрытое введение блокировки до добра не доводит. Завтра тебе понадобится несколько последовательных добавлений и удалений — будем вводить в базовый интерфейс метод AddAndRemoveAll? А знаешь в чем самое веселое — вариант с хелперами легко и непринужденно превращается в вариант с методами класса, причем, благодаря extension методам, еще и абсолютно прозрачно для прикладного кода, использующего ISet, на уровне исходников (т.е. код надо просто перекомпилировать). А вот если ты вкрячил AddAll в ISet, а в результате никаких синхронизаций не понадобилось, выкинуть его оттуда будет ой как непросто. И придется несчастным реализаторам копипейстить один и тот же код твоих AddAll. Так где здесь унылое гавно в дизайне?
Z>Так вот вполне реалистичная ситуация когда появившееся требование ложится на дизайн с вынесенным методом гораздо хуже чем на экземплярный.
Пока что я вижу обратное.
AVK>>Кого списали в канализацию? Я лично никого в канализацию не списывал. Z>А как же это? AVK>>Неа, унылое гавно, это когда в уже существующих методах вдруг появляется блокировка
То есть факт, который работал в нашу пользу — это когда в уже существующих методах вдруг появляется блокировка?
Слушай, мне совершенно не интересно доказывать, что я прав. Если тебе так будет приятно — я признаю что прав ты и больше не буду с тобой спорить.
... << RSDN@Home 1.2.0 alpha 4 rev. 1095 on Windows Vista 6.0.6001.65536>>
Здравствуйте, Ziaw, Вы писали:
Z>>>Тут как раз просто, я его могу переопределить в классе SynchronizedSet. AVK>>И чем это лучше AddAllSync? Z>Лучше тем, что передав экземпляр SynchronizedSet активно исползующийся в другом треде в любой метод с принимающий ISet я не буду гадать, будет там вызван AddAll или нет.
Понимаешь, блокировка такая штука, что ее не стоит прятать внутри. Иначе такие суперрешения будут — мама не горюй, перерасход на блокировках и дедлоки. Только внешний код знает, как правильно расставлять локи, не надо это внутрь коллекций запихивать. Максимум что тут можно сделать — ввести специальную синхронизированную коллекцию с методами, находящимися в публичном интерфейсе класса, но не в ISet, либо отдельный хелпер, увязанный, опять же, не с ISet, а с конкретным синхронизированным классом. Именно так устроен CDS (Coordination Data Structures), в отличие от кривого решения в первом фреймворке.
AVK>>А что, если для одной и той же коллекции нужен и с блокировкой доступ и без онной (как минимум в конструкторе с сигнатурой (IEnumerable<T>) блокировка не нужна)? Вводить специальное свойство еще — IsLockActive? Z>В чьем конструкторе?
В конструкторе твоей синхронизированной коллекции.
AVK>>Как думаешь, почему в ICollection есть свойства IsSynchronized и SyncRoot, а в ICollection<T> уже ничего подобного нет? Z>Почему? Мне правда интересно.
См. выше.
AVK>>Почему близкий по семантике твоему примеру метод Union находится в хелпере, а не в интерфейсе IEnumerable<T>? Z>Как минимум по причине обратной совместимости.
Ага, так значит хелперы таки работают в плане обратной совместимости? Хорошо, тогда следующий вопрос — почему аналогичную ситуацию мы видим в классе Queryable? Ведь IQueryable до этого в фреймворке не было, следовательно никаких проблем с совместимосттью нет?
Z>Я не выдумывал правил по выносу, я только показал, что правило выдуманное IB для улучшения расширяемости может сработать с точностью до наоборот.
Пока что ты этого не показал.
... << RSDN@Home 1.2.0 alpha 4 rev. 1095 on Windows Vista 6.0.6001.65536>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Начинается изменение задачи на ходу. Т.е. требовать в примере с Substring абсолютной конкретики можно, а тут вдруг задача с каждым сообщением меняется произвольным образом.
Где задача поменялась?
Я написал чистую правду, что не планировал показ интерфейса наружу, об этом вполне конкретно говорит модификатор internal в исходном сообщении.
Строкой ниже я написал, что произойдет, если я его таки вынесу. Если тебе кажется, что то "изменение" задачи притянуто за уши — не читай про него, текст ниже описывает проблемы которе происходя при публикации данного интерфейса и более строго типизированого AddAll который предложил ты.
AVK> Если хочешь конкретики — то твое решение никуда не годится, прозрачное и закрытое введение блокировки до добра не доводит. Завтра тебе понадобится несколько последовательных добавлений и удалений — будем вводить в базовый интерфейс метод AddAndRemoveAll? А знаешь в чем самое веселое — вариант с хелперами легко и непринужденно превращается в вариант с методами класса, причем, благодаря extension методам, еще и абсолютно прозрачно для прикладного кода, использующего ISet, на уровне исходников (т.е. код надо просто перекомпилировать).
Точно также легко и непринужденно с совместимостью на уровне исходников метод при необходимости выносится в extensions. О чем мы тогда спорим?
AVK>А вот если ты вкрячил AddAll в ISet, а в результате никаких синхронизаций не понадобилось, выкинуть его оттуда будет ой как непросто. И придется несчастным реализаторам копипейстить один и тот же код твоих AddAll. Так где здесь унылое гавно в дизайне?
Унаследоваться от AbstractSet им религия помешает?
AVK>>>Кого списали в канализацию? Я лично никого в канализацию не списывал. Z>>А как же это? AVK>>>Неа, унылое гавно, это когда в уже существующих методах вдруг появляется блокировка AVK>То есть факт, который работал в нашу пользу — это когда в уже существующих методах вдруг появляется блокировка?
Нет, более общий факт, когда начинает требоваться полиморфное поведение вынесенного наружу метода.
AVK>Слушай, мне совершенно не интересно доказывать, что я прав. Если тебе так будет приятно — я признаю что прав ты и больше не буду с тобой спорить.
Признай Я только за.
Здравствуйте, Ziaw, Вы писали:
Z>Где задача поменялась?
То был метод с единственной реализацией, то вдруг синхронизация откуда то вылезла.
Z>Я написал чистую правду, что не планировал показ интерфейса наружу, об этом вполне конкретно говорит модификатор internal в исходном сообщении.
Но при этом ты решил все условия задачи сразу не писать. Наверное надеялся поймать.
Понимаешь — примеры хороши, если они что то иллюстрируют. А вот примеры в качестве доказательств обобщенных вещей — никуда не годятся. Именно потому что они тут же сводят все обсуждение с принципа на конкретный код.
Т.е., в твоем случае, конструктивным было бы сразу продемонстрировать исходный пример, появление синхронизации, возможные примеры решения в случае с хелперами и большим интерфейсом. Вот тогда можно было бы обсудить конструктивно — что и как можно сделать в каждом случае.
Z>Точно также легко и непринужденно с совместимостью на уровне исходников метод при необходимости выносится в extensions.
Увы нет. Добавление элемента в контракт всегда проще, чем удаление его оттуда.
Z>Унаследоваться от AbstractSet им религия помешает?
То есть мы еще и абстрактный класс нарисуем? И тесно увяжем все реализации с твоим AbstractSet? А если пользюковые классы имеют свою иерархию наследования, куда твой AbstractSet вкрячить не получится? Например от MBR надо наследоваться?
AVK>>То есть факт, который работал в нашу пользу — это когда в уже существующих методах вдруг появляется блокировка? Z>Нет, более общий факт, когда начинает требоваться полиморфное поведение вынесенного наружу метода.
Появление полиморфизма там, где его до этого не было — это серьезнейшая перестройка кода, ловить копейки на этом фоне уже бессмысленно. Опять же — буквально недавно ты все конкретики требовал. А теперь что — конкретика уже не катит?
Z>Признай Я только за.
Хорошо, ты прав. Теперь можно обходится без подобных приемчиков?
... << RSDN@Home 1.2.0 alpha 4 rev. 1095 on Windows Vista 6.0.6001.65536>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Понимаешь, блокировка такая штука, что ее не стоит прятать внутри. Иначе такие суперрешения будут — мама не горюй, перерасход на блокировках и дедлоки. Только внешний код знает, как правильно расставлять локи, не надо это внутрь коллекций запихивать. Максимум что тут можно сделать — ввести специальную синхронизированную коллекцию с методами, находящимися в публичном интерфейсе класса, но не в ISet, либо отдельный хелпер, увязанный, опять же, не с ISet, а с конкретным синхронизированным классом. Именно так устроен CDS (Coordination Data Structures), в отличие от кривого решения в первом фреймворке.
Пример был просто придуман на скорую руку для демонстрации появления требования приводящего к полиморфному поведению вынесенного метода. Или такое требование реально только в высосаных из пальца ситуациях?
За советы по поводу синхронизации спасибо, познавательно.
AVK>>>А что, если для одной и той же коллекции нужен и с блокировкой доступ и без онной (как минимум в конструкторе с сигнатурой (IEnumerable<T>) блокировка не нужна)? Вводить специальное свойство еще — IsLockActive? Z>>В чьем конструкторе? AVK>В конструкторе твоей синхронизированной коллекции.
А зачем в конструкторе вызывать виртуальный метод?
AVK>Ага, так значит хелперы таки работают в плане обратной совместимости?
Я гдето утверждал обратное? Всегда считал их хорошим средством расширения.
AVK>Хорошо, тогда следующий вопрос — почему аналогичную ситуацию мы видим в классе Queryable? Ведь IQueryable до этого в фреймворке не было, следовательно никаких проблем с совместимосттью нет?
Потому, что в случае экземплярной реализации всем реализациям пришлось бы наследоваться от абстрактного класса, а это не всегда приемлемо.
Z>>Я не выдумывал правил по выносу, я только показал, что правило выдуманное IB для улучшения расширяемости может сработать с точностью до наоборот. AVK>Пока что ты этого не показал.
Буду дальше стараться. Для меня это очевидно.
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>Еще как упала. Раз уж была упомянута STL: хороший пример — разделение алгоритмов и контейнеров: все что необходимо, так это предоставить пару итераторов — все остальное начнет работать автоматически. То же и для алгоритмов поверх любых контейнеров. А что будет если слить все в кучу ?
.Net Framework Class Library?
ЮЖ>Здесь множество причин для изменений. Я про это.
Ты как-то криво обозвал SRP. SRP как и любой другой принцип не самоцель и не надо под алгом больбы с классами занимающимися сразу несколькими задачами измельчать всё что можно и нельзя. Есть классы, которые не просто содержат сотню методов, это абсолютно нормально в предметной области их использования.
ЮЖ>Тогда зачем вообще раскидывать? — один класс на библиотеку, да и не мучиться...
Раскидывать надо не ради процесса раскидывания, а ради построения понятного, удобного интерфейса.
ЮЖ>Из нескольких классов, которые можно использовать независимо, проще собирать то что необходимо.
Их нельзя использовать независимо. В хелпер функции выносили потому что можно, а не по логическим признакам предметной области. То есть ничего не упростили.
A>>И получить STL где у сттроки нет нормального find ЮЖ>А нормальный это какой ? с регэкспами и поиском через гугл?
Досстаточно регэкспов.
ЮЖ>Может быть. В зависимости от задачи. Со строками проблема в том, что там слишком много потенциально настраиваемых моментов, и при попытке свалить все в кучу получится вышеупомянутый реструктуризатор.
Да вот System.String как-то всем хватает.
ЮЖ>Не надо доводить до маразма кажущееся "удобство" в виде автокомплита. Иначе чем объяснить изначальное существование в классе методов которых там не должно быть?
Соответствие логике предметной области.
ЮЖ>Ничего против автокомплита не имею, но неужели это действительно может рассматриваться как критерий выбора библиотеки ?
Близость объектной модели и реалий предметной области — критерий.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Ziaw, Вы писали:
AVK>Понимаешь — примеры хороши, если они что то иллюстрируют. А вот примеры в качестве доказательств обобщенных вещей — никуда не годятся. Именно потому что они тут же сводят все обсуждение с принципа на конкретный код. AVK>Т.е., в твоем случае, конструктивным было бы сразу продемонстрировать исходный пример, появление синхронизации, возможные примеры решения в случае с хелперами и большим интерфейсом. Вот тогда можно было бы обсудить конструктивно — что и как можно сделать в каждом случае.
Ок. Признаю, что так было бы честнее. Но я не знал бы что возразить на аргумент типа "сам дурак раз так спроектировал".
Z>>Точно также легко и непринужденно с совместимостью на уровне исходников метод при необходимости выносится в extensions. AVK>Увы нет. Добавление элемента в контракт всегда проще, чем удаление его оттуда.
Чем?
AVK>Хорошо, ты прав. Теперь можно обходится без подобных приемчиков?
Постараюсь.
Здравствуйте, Ziaw, Вы писали:
Z>Пример был просто придуман на скорую руку для демонстрации
Вот уж нет. Если бы он был для демонстрации — ты бы сразу свою мысль продемонстрировал, а не тянул бы кота за хвоста, расписывая свой пример на несколько сообщений.
Z> появления требования приводящего к полиморфному поведению вынесенного метода
Посчитай — сколько сообщений между твоим начальным примером и появлением слова "полиморфный". Вот это и называется — меняем пример на ходу.
Z>За советы по поводу синхронизации спасибо, познавательно.
Зато абсолютно не в тему. Что и ожидалось.
AVK>>В конструкторе твоей синхронизированной коллекции. Z>А зачем в конструкторе вызывать виртуальный метод?
То есть у тебя будут две реализации AddAll внутри, одна виртуальная, другая нет? Да и почему виртуальный? Для реализации интерфейса виртуальность не обязательна, интерфейс свою виртуальность добавит.
AVK>>Ага, так значит хелперы таки работают в плане обратной совместимости? Z>Я гдето утверждал обратное?
Что тогда ты пытаешься доказать?
AVK>>Хорошо, тогда следующий вопрос — почему аналогичную ситуацию мы видим в классе Queryable? Ведь IQueryable до этого в фреймворке не было, следовательно никаких проблем с совместимосттью нет? Z>Потому, что в случае экземплярной реализации всем реализациям пришлось бы наследоваться от абстрактного класса
IQueryable, как несложно догадаться из названия, это интерфейс и никакого наследования от абстрактного класса он не требует.
... << RSDN@Home 1.2.0 alpha 4 rev. 1095 on Windows Vista 6.0.6001.65536>>
Здравствуйте, Ziaw, Вы писали:
Z>>>Точно также легко и непринужденно с совместимостью на уровне исходников метод при необходимости выносится в extensions. AVK>>Увы нет. Добавление элемента в контракт всегда проще, чем удаление его оттуда. Z>Чем?
Тем, что про новый член никто не знает, и его добавление по сути совсем не меняет семантику использующего кода (если только не умудрились дать возможность с его помощью поломать инварианты). А вот удаление метода безусловно меняет семантику тех кусков, которые его использовали, и над этими кусками уже надо думать мозгой, что делать.
... << RSDN@Home 1.2.0 alpha 4 rev. 1095 on Windows Vista 6.0.6001.65536>>
AVK>Что тогда ты пытаешься доказать?
что правило выдуманное IB для улучшения расширяемости может сработать:
1. для ухудшения читабельности кода (занятие бесполезное, поскольку измерить читабельность нечем), а закладываемая расширяемость никогда не появится. (для всех случаев выноса кроме экстеншен методов)
2. для ухудшения расширяемости
AVK>>>Хорошо, тогда следующий вопрос — почему аналогичную ситуацию мы видим в классе Queryable? Ведь IQueryable до этого в фреймворке не было, следовательно никаких проблем с совместимосттью нет? Z>>Потому, что в случае экземплярной реализации всем реализациям пришлось бы наследоваться от абстрактного класса AVK>IQueryable, как несложно догадаться из названия, это интерфейс и никакого наследования от абстрактного класса он не требует.
Я в курсе, даже пытался его реализовать.
Имелось в виду, что в случае включения всех методов в контракт интерфейса в каждой реализации пришлось бы либо копипастить имплементацию либо наследоваться от класса где они уже есть.
Здравствуйте, Ziaw, Вы писали:
Z>1. для ухудшения читабельности кода
Пример этого не продемонстрировал.
Z> (занятие бесполезное
Ага, особенно если учесть, что код с использванием extension методов идентичен коду использования instance методов вплоть до символа.
Z>2. для ухудшения расширяемости
Пример этого не продемонстрировал.
AVK>>IQueryable, как несложно догадаться из названия, это интерфейс и никакого наследования от абстрактного класса он не требует. Z>Я в курсе, даже пытался его реализовать. Z>Имелось в виду, что в случае включения всех методов в контракт интерфейса в каждой реализации пришлось бы либо копипастить имплементацию либо наследоваться от класса где они уже есть.
Ну вот, ты и сам можешь ответить на свой вопрос, почему раздувание твоего гипотетического ISet — идея совсем не замечательная.
... << RSDN@Home 1.2.0 alpha 4 rev. 1095 on Windows Vista 6.0.6001.65536>>