Pull to refresh

Comments 16

У вас картинка не правильная, если пост про Лисков, то картинка должна быть такой
image
Ключевое слово probably. Забавный мем.
UFO just landed and posted this here
Но на практике в составе .Net Framework нет ни одного компонента который корректно работает с (NewItems.Count > 1) и (OldItems.Count > 1). В лучшем случает бросается исключение, в худшем — все элементы кроме первого просто игнорируются.
UFO just landed and posted this here
Add и Remove точно так же могут сигнализировать о множественном изменении.

Работая с ObserverableCollection, вы на практике хотя бы раз сталкивались с таким случаем? Можете пожалуйста привести пример?
У ObserverableCollection нет метода AddRange. Каждый раз при вызове метода Add (который принимает в качестве параметра ровно один элемент) срабатывает событие, у которого в NewItems находится всегда ровно один элемент. Так что для NotifyCollectionChangedAction.Add то что написано в msdn истинно и на практике.
UFO just landed and posted this here
Приведённый в статье совет про выбор из двух контрактов актуален вне зависимости от того, является ли один контракт интуитивными ожиданиями, или же оба контракта являются формальными. Повторюсь, в случае, если вы реализуете наследника, опирайтесь на наиболее конкретный и специфичный контракт среди двух.
Формальный контракт в .NET Framework 4 говорит, что Add означает «One or more items were added to the collection.». Формальный контракт в .NET Framework 4.5 для Add — «An item was added to the collection.».
Сделав так, как вы говорите, вы нарушите публичный формальный контракт из версии 4.5.
Нарушение контракта, являющегося интуитивными ожиданиями — тема тонкая и холиварная, но вот нарушение формального контракта — бесспорный факт. Рекомендую при наследовании использовать контракт с наибольшими ограничениями — т.е. добавление единственного элемента, а при использовании — с наименьшими ограничениями, т.е. добавление нескольких элементов.
Для начала, рассматриваемая часть контракта ObservableCollection определяется интерфейсом INotifyCollectionChanged
Самая горячая часть — NotifyCollectionChangedEventArgs
И все проблемы связаны отнюдь не с неким «реальным контрактом», а с застарелыми багами в реализации.
Например, никто не запрещает сообщать о добавлении сразу пачки элементов… кроме кривых контролов из поставки WPF, которые в ответ на такое плюются исключениями. Как это сказывается на производительности, надеюсь, всем понятно.
До версии 4.5, впрочем, была возможность исправить ситуацию — NotifyCollectionChangedAction.Reset, который заставлял контрол принудительно
обновиться полностью.
Это позволяло создавать свои реализации INotifyCollectionChanged с хорошей производительностью при интенсивных обновлениях.
Но что мы видим в 4.5?
Добрый вендор:
  • изменил опубликованный интерфейс (-1)
  • сломал обратную совместимость (-1)
  • обрушил производительность (-1)
  • зато легализовал творчество разработчиков, неспособных прочесть спецификацию (+100500)

Что интересно, в русской версия MSDN для 4.5 ничего не поменялось.
обрушил производительность (-1)
зато легализовал творчество разработчиков, неспособных прочесть спецификацию (+100500)

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


И все проблемы связаны отнюдь не с неким «реальным контрактом», а с застарелыми багами в реализации.

В любой непонятной ситуации проще всего не раздумывая обвинить во всём конечных исполнителей. Однако давайте подумаем, а почему конечные исполнители реализовали «кривые контролы из поставки WPF» именно так? Может быть они были обиженными на весь мир садистами, намеренно допустившими ошибку? Звучит бредово. А может быть их интуитивные ожидания о поведении ObservableCollection отличались от того, что написано в msdn? Звучит правдоподобно. Итак, есть проблема — интуитивные ожидания большинства разработчиков не совпадают с описанием в документации. Какие тут могут быть решения? Ну, проще всего не раздумывая возложить ответственность за решение проблемы на конечных исполнителей. Мол, ребята, вызубрите наизусть весь msdn и регулярно его повторяйте. Поможет это избавиться от багов? Я думаю, не поможет. Вариант второй — сделать так, чтобы интуитивные ожидания большинства программистов совпадали с описанием в документации. Именно так я оцениваю случай с изменениями в документации. Если есть конструктивная критика — я буду рад услышать чужое мнение. Фраза же «всё сказанное чепуха, во всём виноваты конечные исполнители, наделавшие багов» не очень похожа на конструктивную критику, потому что не раскрыта мысль, а почему именно чепуха, почему «все проблемы связаны отнюдь не с неким «реальным контрактом»».
Немного поясню. В .NET Framework 4 сказано, что Add означает, что один или несколько элементов добавлены в коллекцию, а разработчики, судя по всему, руководствовались интуитивными ожиданиями, сформированными ObservableCollection, что Add означает добавление одного элемента. А если бы в документации было сказано, что Add означает добавление одного элемента, то никто бы не пытался реализовывать коллекции таким образом, что Add означает добавление нескольких элементов, и не сталкивался бы с проблемами. Ещё было бы неплохо в документации указать, что Reset означает очистку коллекции и добавить элемент, сигнализирующий о произвольном изменении коллекции. Совпадение интуитивных ожиданий и формальных требований уменьшает вероятность ошибки. В данном же случае, судя по всему, формальная документация писалась для абстрактного интерфейса, а интуитивные ожидания формировались на основании конкретного класса.
Ещё было бы неплохо в документации указать, что Reset означает очистку коллекции и добавить элемент, сигнализирующий о произвольном изменении коллекции.

Это еще хуже. Добавление элемента в публичный enum ломает обратную совместимость непосредственно по коду.
А если бы в документации было сказано, что Add означает добавление одного элемента, то никто бы не пытался реализовывать коллекции таким образом, что Add означает добавление нескольких элементов, и не сталкивался бы с проблемами.

«Интуитивные разработчики» все равно написали бы по-своему, они же документацию не читают по определению.
В любой непонятной ситуации проще всего не раздумывая обвинить во всём конечных исполнителей

Нет никакой непонятной ситуации и нет никаких обвинений в адрес конечных исполнителей. Есть опубликованный и документированный интерфейс, есть его реализации, есть клиенты, которые его используют.
И то, и другое и третье может содержать ошибки. В данном случае вместо исправления ошибок в клиентах внесли дефект в давно опубликованный и документированный интерфейс.
Однако давайте подумаем, а почему конечные исполнители реализовали «кривые контролы из поставки WPF» именно так?

Это не имеет значения — важен результат.
А может быть их интуитивные ожидания о поведении ObservableCollection отличались от того, что написано в msdn? Звучит правдоподобно.

Но тоже отнюдь не комплиментарно. «Интуитивные ожидания» в данном случае синоним непрофессионализма и глупости.
Мол, ребята, вызубрите наизусть весь msdn и регулярно его повторяйте.

Есть способ гораздо проще. Читайте что написано в документации по интерфейсу при его реализации.
В данном же случае, судя по всему, формальная документация писалась для абстрактного интерфейса, а интуитивные ожидания формировались на основании конкретного класса

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

А если причина не важна, то как, спрашивается, учиться на чужих ошибках? Как не совершать подобных ошибок в будущем? Одна из целей моей статьи — предостеречь читателей от подобных ошибок. Если для вас всё это не имеет значения — ну что же, ваше право, можете дальше игнорировать интуитивные ожидания разработчиков, это останется на вашей совести.
Вообще, мой вопрос был, почему вы говорите, что «все проблемы связаны отнюдь не с неким «реальным контрактом»», а в ответ я услышал лишь кучу эмоций по поводу нарушения обратной совместимости и оценок компетентности разработчиков WPF. Вы, несомненно, имеете полное право на эмоции, и спасибо что ими поделились, но обсуждение темы по существу было бы гораздо приятнее и полезнее.
«Интуитивные разработчики» все равно написали бы по-своему, они же документацию не читают по определению.
Интуитивные ожидания формируются не случайным образом, а на основании поведения конкретного класса. Я думал, что довольно подробно описал этот процесс, даже два примера привёл. Мне кажется, вы меня регулярно троллите. В прошлой статье вы меня 5 раз спросили про утечки памяти и слабые события, и я вам 5 раз ответил: [1], [2], [3], [4], [5]. В этой статье всё с ног на голову пытаетесь перевернуть.

Ладно, если по существу, чтобы не было бы разрыва между интуитивными ожиданиями и документацией, нужно было или в классы, реализующие интерфейс, добавить методы AddRange, RemoveRange, или, повторюсь, в документации написать, что можно добавлять только по одному элементу.
Sign up to leave a comment.

Articles