Как стать автором
Обновить
22
0
Игорь Моисеев @kayan

Технический директор, специалист широкого профиля

Отправить сообщение
Возможно, я не в теме про телевидение или не так понимаю «непоправимое». В любом случае, добавил ваш пост в избранное — надеюсь, вернуться в нему в следующей контрольной точке — началу следующего года.
У меня такой же вопрос — зачем им фотошоп?? :)
опять мифические сотрудники которых никто не видел и не знает. Хотя будь это любая коммерческая организация, я думаю виновных уже давно бы нашли.

Не нашли бы. Если дело не является особо важным и публичным, конечно. За контрафакт организацию (в нашей области, по крайней мере) засудить очень тяжело, если они сами не наделают глупостей.

В ситуации с госучреждениями, более того, я считаю, что действительно проблемы в основном идут не от установок начальства и от распилов, а от безалберности работников. Ставят сами Word, например, сами ставят (как в Роскомнадзоре, все скорее) Photoshop. Просто им лично так удобнее или подкалымить на работе надо. Государство можно осудить за то, в основном, что оно недостаточно сильно следит за «перевоспитанием», тут согласен в целом с автором.
Интересный вопрос, какое правительство адекватней — которое за всеми следит или которое все запрещает. Но пока, хотя с этой цензурой в этом году было много шума, ничего непоправимого не произошло (насколько мне известно, может, кто просветит).
В Америке, например?
Тогда появляется возможность присвоить значение целиком элементу массива. Неизменяемость типа ключа не спасает.

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

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

И хэш определить и неизменяемой сделать.
Хэш могут потом и поменять, включив по ошибке потенциально изменяемое поле.

Вопрос не в том, зачем изменять структуру (хотя и в этом случае сразу вопрос — а почему не класс?), а зачем передавать изменяемую структуру как ключ.
Либо добавлять вспомогательный метод CloneWithMovedEdge1.

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

Например, предоставляющей исходный массив этих ключей (не спрашивайте зачем, случае разные бывают).
Вариант 1.

Я не очень понял, зачем эти варианты. Речь идет о минимализации возможностей прострелить себе ногу. С точки зрения .NET ситуация со структурами, ссылающимися на классы, а тем более реализация своего хэш-кода для класса — вполне возможные вещи.
И чтобы другие разработчики, не знакомые с тонкостями реализации и не знающие, что «нельзя переопределять у этого класса хэш-код, а то в другом месте коллекция упадет», не стреляли по ногам, предлагается политика, позволяющая обезопаситься в этом и других случаях.
Легко ответить на вопросы, зачем переопределять хэш-код и зачем передавать структуру как ключ, но на вопрос зачем передавать как ключ изменяемую структуру — гораздо сложнее.
UPD: проблема может и возникнуть, см тут
В общем случае хэш-код как раз должен быть неизменяемым после инициализации ключа, т. к. реализации таблиц могут быть всякие. В частном же — опять у себя увидел неточность, спасибо — почти всегда все хорошо для стандартных коллекций. А вот оно почти:
void Main()
{    
	var key1 = new Key{
                             RefField = new Reference {InnerField = 5},
                             ValueField = 3
              };
	SetKey(key1);
	"Before change".Dump();
	ShowSetKeyHashCode();
	key1.ValueField = 3;
	"After value field change".Dump();
	ShowSetKeyHashCode();
	key1.RefField.InnerField = 8;
	"After reference field change".Dump();
	ShowSetKeyHashCode();	
}

private Key _setKey;

void SetKey(Key key)
{
   _setKey = key;
}

void ShowSetKeyHashCode()
{
   ShowKeyHashCode(_setKey);
}

void ShowKeyHashCode(Key key)
{
   string.Format("Val:{0}, ref: {1}, hash: {2}",key.ValueField,key.RefField.InnerField,key.GetHashCode()).Dump();   
}

class Reference
{
   public int InnerField;
   public override int GetHashCode()
   {
      return InnerField;
   }
}

struct Key
{
   public Reference RefField;
   public int ValueField; 
}

Мы инициализируем у структуры Key поле RefField и отдаем эту структуру в качестве ключа. Несмотря на то, что в стандартных реализациях коллекций мы не сможем достучаться до непосредственно значения ключа типа Key (всегда будем получать копию), поменять значение поля Field у известного нам объекта типа Reference мы можем. Соответственно, сохраненный нами в коллекции ключ будет иметь не тот хэш-код, что при занесении в коллекцию, что приведет к невозможности корректного поиска этого ключа.
И это именно та ситуация, где поле типа Reference должно быть либо immutable (readonly не спасет), либо value-type.
В нашем случае спасает, например, если поменять поля в структуре Key местами. Попробуйте.
Да, я немножко смешал в кучу общий случай, с возможно ссылочным объектом и некоторой абстрактной хэш-таблицей. Для стандартных .NET коллекций такая проблема со структурами не возникнет — потому структуры и используют в качестве ключей.
Но комментарий разработчиков (и сам автор), как мне кажется, описывает именно общую возможную ситуацию с хэш-кодом структуры.
Имеется в виду, что если мы используем хэш-код по прямому назначению — т.е. для оптимизации поиска, то изменение объекта, который мы ищем, может привести к невозможности его повторного поиска — сохраненный алгоритмом хэш автоматически не поменяется (в стандартных реализациях). Соответственно, если уж мы хотим менять объект, то менять его надо так, чтобы хэш оставался неизменным, а именно (в данном случае) все, кроме первого поля.

Хотя ситуация с изменением объекта после его помещения в хэш таблицу сама по себе не очень хорошая.

И это, вместе с остальным, является аргументом, почему структуры, которые чаще всего используют как ключи, надо стараться делать неизменяемыми. Об этом «остальном» можно почитать тут: stackoverflow.com/questions/441309/why-are-mutable-structs-evil. Ну и у Липперта в блоге.
А мне понравилось. Хотя, конечно, «продолжение следует» и неформатированность. :) Если бы по данном реферату автор по заявкам смог бы раскрыть затронутые темы — было бы здорово, но такое ощущение, будто это всего лишь краткое вступление перед изложением сабжевой проблемы. Буду ждать продолжения.
И это не панацея. Сборщик мусора может решить, что чистить память совершенно необязательно. Чтобы отучить его думать самостоятельно, надо вызвать перегруженный метод Collect с GCCollectionMode.Forced.
Более того, даже подобный вызов у меня в 1 случае из 100, наверное, не помогает.
Будем надеяться, что это они просто новых скинов добавили.
Это не мой NonShared, это MEF-овский NonShared. :) И policy, которую я перевожу как политика, тоже. Единственно, что я называю по-другому — это та самая область видимости, которая в MEF есть «политика создания». Почему область видимости, а не время жизни? Потому, что контейнер не управляет временем жизни объектов в полной мере, он их максимум только создает. Моя политика, наравне с политиками MEF собственно и определяет область видимости объекта.
В сторону глобализации, если можно так выразиться. :) Т.е. в NonShared может лежать ограниченный областью видимости объект, а в нем — Shared.
Наоборот, как несложно догадаться, быть не может. Точнее, атрибуты-то можно написать, но область видимости все равно будет от самого глобального объекта.
Если у меня есть супернавороченная универсальная система, которая может все, но которую надо сконфигурировать, то для решения задачи, которая является родной для более простой системы, решающей непосредственно эту задачу, кода надо писать больше.
Грубо говоря, чем больше у ножика лезвий, тем тяжелее найти нужное. Но это мы уже вообще в глубокую философию ушли. :)
По теме же советую посмотреть на возможности MEF 2 (работа с обобщениями, RegistrationBuilder, дочерние контейнеры). Разумеется, он по-прежнему аскетичен, по сравнению с тем же автофаком например, но, как мне кажется, в 80% приложений его хватит за глаза.
Да меф тут не при чем. С точки зрения неповторяемости он помогает так же, как и все остальные контейнеры, только в каких-то случаях (для которых в нем не предусмотрено готового сценария) будет больше кода. Зато в других, за счет того, что в нем меньше возможностей и, соответственно, конфигураций, кода будет меньше.
В каких-то ситуациях будет разумно вообще контейнер не использовать.
Вот основная моя мысль в чем, которую я пытаюсь донести — вместо того, чтобы думать, как красиво реализовать декораторы и стратегии, лучше думать о том, как обойтись без них. Для этого придумана аббревиатура KISS, например. :) И полнофункциональные в своей области, но не имеющие ничего лишнего за ней средства очень этому способствуют. Зачем думать о том, как контролировать разработчиков, чтобы они в сложности не запутались и не наизобретали лишнего, если можно в принципе этой сложности не допускать?
Опасность опять же шаблонов в том, что, увлекшись кодом, можно забыть о том, что за ним находится.
Причем здесь MEF? :) Он и есть полнофункциональное средство в своей области без всякого лишнего.
И кстати, с ликвидацией то же проблем не будет в нормальном контейнере.

Да будет, когда неясно, когда и кому объект ликвидировать.
Ну контейнер то как раз и создан, что бы быть универсальной фабрикой=)

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

Самое страшное в AOP в неумелых руках (я не имею в виду вас) — совершенно неочевидные и, подчас, конфликтные инъекции. Собственно, неконтролируемое смешивание всего и вся, как мне кажется, и есть самое серьезное ограничение подобного подхода — ну типа как множественное наследование, только еще менее очевидное. Продуманная архитектура, практически устраняет необходимость в широком применении AOP. А сделать инъекцию со своим временем жизни вполне возможно, ну это уже в статью пойдет. Обвешивать проксями и прочим без сложностей тоже можно, при условии, что написанный пользователем класс позволяет подобные паттерны, и это смотрится вполне естественно в MEF…

Ну и самое главное, это то, что для MEF необходимо в свой код тащить специфичные для контейнера атрибуты.

Совершенно необязательно. Есть класс RegistrationBuilder.
Допускаю, что при определенном рвении можно над MEF нарисовать это все, но зачем?
Многия знания, как говорится, рождают многия печали. :) Обилие возможностей приводит к каше на проекте, когда сложно разобраться, какой объект как получается и что из себя представляет (это, конечно, на больших проектах и в команде чувствуется).
Плюсы мефа я уже указал — простой в использовании, наглядный и надежный вроде как фреймворк для сбора композиции. Зачем пилить полено лазером, если можно пилой?

Информация

В рейтинге
Не участвует
Откуда
Иннополис, Татарстан, Россия
Дата рождения
Зарегистрирован
Активность

Специализация

Fullstack Developer, Chief Technology Officer (CTO)
Lead
C#
.NET Core