Здравствуйте, _FRED_, Вы писали:
L>>Широко-распространенные бибилиотеки де-факто и задают стандарт. L>>За примером далеко ходить не надо: Hashtable из .Net Framework-а.
_FR>Не очень удачный пример неудачно спроектированного контейнера. Чего с него пример брать? Взгляни на более продуманный IDictionary<,>.
С чего ты взял, что он более продуманный? Он просто другой.
Здравствуйте, Lloyd, Вы писали:
L>>>Широко-распространенные бибилиотеки де-факто и задают стандарт. L>>>За примером далеко ходить не надо: Hashtable из .Net Framework-а.
_FR>>Не очень удачный пример неудачно спроектированного контейнера. Чего с него пример брать? Взгляни на более продуманный IDictionary<,>.
L>С чего ты взял, что он более продуманный? Он просто другой.
Ты реализацию Hashtable.get_Item видел? c Thread.Sleep внутри? А не думал, почему в System.Collections.Generic не сделали никакой поддержки многопоточности вообще? Hashtable пытались сделать суперпростой и суперфункциональной одновременно, что бы любой дурак понял, как ей пользоваться.
Наверное, это было важно в первом релизе нового фреймворка, что бы сложными идиомами не отпугнуть армию индусов. С этой задачей, не спорю, Hashtable справилась.
А в "наследство" нам достались такие вот хитрости:
Hashtable map = …;
var count1 = map.Count;
var item = map[key];
map[key] = item;
var count2 = map.Count; // count2 может отличаться от count1.
У меня сейчас нет под рукой Framework Design Guidelines, но, думаю, не сильно ошибусь, если предположу, что в ней советуют вместо ArrayList использовать List<object>, а вместо Hashtable Dictionary<object, object> (если более точные типы указать нельзя).
Кстати, ни в стл::мап, ни в МФЦ::ЦМар нету такой функциональности, что бы по отсутствующему ключу возвращать что-то специальное. Дизайн самик контейнеров сделан так, что этот вопрос не стоит. А в Hashtable стоит. Вернее, стоял. До появления первых бет второго фреймворка, когда стало ясно, что всё вскоре будет по-другому и симпотичнее.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Lloyd, Вы писали:
K>>чем бы заменить слишком длинное имя item_get_or_create?
L>Умные дядьки рекомендуют для облегчения жизни явно разделять функции запрашивающие состояние и меняющие его. L>Так что бей на два метода и не ошибешься.
Наоборот, "умные дядьки" делают то, что народу нужно. Для примера: умные дидьки из Оракла сделали ALTER_OR_CREATE (точно не знаю, как зовётся, но смысл, думаю, понятен), а другие дядьки из MSSQL, которых мы не будем никак характеризовать, "жмутся". Разработчикам БД это ой как жизнь портит.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>А в "наследство" нам достались такие вот хитрости:
Это разве хитрости? Один знакомый "фокусник" любил писать вот в таком духе:
string path = CurDir.Files[name]; // здесь очень весело - если файла с таким именем нет в коллекции, то он не только в нее добавляется, но еще и создается на диске ;)
Здравствуйте, Undying, Вы писали:
U>В данном случае сторонним эффектом является создание элемента, а не его гарантирование или принуждение, поэтому в названии метода должно присутствовать слово create (или его точный синоним), а не слова связанные со сторонним эффектом метода весьма иносказательно.
collection.EnsureItem(val) — ясно и однозначно понятно любому, кто знает английский
Здравствуйте, Andrei F., Вы писали:
_FR>>А в "наследство" нам достались такие вот хитрости: AF>Это разве хитрости? Один знакомый "фокусник" любил писать вот в таком духе:
AF>string path = CurDir.Files[name]; // здесь очень весело - если файла с таким именем нет в коллекции, то он не только в нее добавляется, но еще и создается на диске ;)
AF>Очень свежее решение. Нетривиальное
Да уж Операция-то, конечно, сама по себе нормальная, но называться ждолжна не "индексер", а Ensure…, кстати о теме топика
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Ты реализацию Hashtable.get_Item видел? c Thread.Sleep внутри? А не думал, почему в System.Collections.Generic не сделали никакой поддержки многопоточности вообще? Hashtable пытались сделать суперпростой и суперфункциональной одновременно, что бы любой дурак понял, как ей пользоваться.
Ссылочку на авторство этого высказывания дашь?
Да, кстати, как связаны дизайн контейнера и его реализация? Как-то не могу понять.
_FR>Наверное, это было важно в первом релизе нового фреймворка, что бы сложными идиомами не отпугнуть армию индусов. С этой задачей, не спорю, Hashtable справилась.
О каких сложных идиомах в случае Dictionary идет речь?
_FR>А в "наследство" нам достались такие вот хитрости: _FR>
Ну вот, то "не отпугнуть индусов", то "хитрости". Ты уж как-нибудь определись.
_FR>У меня сейчас нет под рукой Framework Design Guidelines, но, думаю, не сильно ошибусь, если предположу, что в ней советуют вместо ArrayList использовать List<object>, а вместо Hashtable Dictionary<object, object> (если более точные типы указать нельзя).
Понятно, что List, а не ArrayList. Только это аргументом за то или иное поведение индексера ну никак не является.
Здравствуйте, Andrei F., Вы писали:
L>>Умные дядьки рекомендуют для облегчения жизни явно разделять функции запрашивающие состояние и меняющие его.
AF>Для облегчения жизни себе или пользователю твоей библиотеки?
Здравствуйте, Lloyd, Вы писали:
_FR>>Ты реализацию Hashtable.get_Item видел? c Thread.Sleep внутри? А не думал, почему в System.Collections.Generic не сделали никакой поддержки многопоточности вообще? Hashtable пытались сделать суперпростой и суперфункциональной одновременно, что бы любой дурак понял, как ей пользоваться.
L>Ссылочку на авторство этого высказывания дашь?
Какого именно?
L>Да, кстати, как связаны дизайн контейнера и его реализация? Как-то не могу понять.
А так, что из плохого дизайна хорошую реализацию сложно сделать.
_FR>>Наверное, это было важно в первом релизе нового фреймворка, что бы сложными идиомами не отпугнуть армию индусов. С этой задачей, не спорю, Hashtable справилась.
L>О каких сложных идиомах в случае Dictionary идет речь?
Об использовании TryGetItem
_FR>>А в "наследство" нам достались такие вот хитрости:
L>Ну вот, то "не отпугнуть индусов", то "хитрости". Ты уж как-нибудь определись.
Я определён: "хитрости" могли бы "отпугнуть индусов".
_FR>>У меня сейчас нет под рукой Framework Design Guidelines, но, думаю, не сильно ошибусь, если предположу, что в ней советуют вместо ArrayList использовать List<object>, а вместо Hashtable Dictionary<object, object> (если более точные типы указать нельзя).
L>Понятно, что List, а не ArrayList. Только это аргументом за то или иное поведение индексера ну никак не является.
Здравствуйте, _FRED_, Вы писали:
_FR>>>Ты реализацию Hashtable.get_Item видел? c Thread.Sleep внутри? А не думал, почему в System.Collections.Generic не сделали никакой поддержки многопоточности вообще? Hashtable пытались сделать суперпростой и суперфункциональной одновременно, что бы любой дурак понял, как ей пользоваться.
L>>Ссылочку на авторство этого высказывания дашь?
_FR>Какого именно?
На то, что разработчики "пытались сделать суперпростой и суперфункциональной одновременно, что бы любой дурак понял, как ей пользоваться".
L>>Да, кстати, как связаны дизайн контейнера и его реализация? Как-то не могу понять.
_FR>А так, что из плохого дизайна хорошую реализацию сложно сделать.
Гм. Мы вроде как обсуждали поведение индексера. Что могло помешать им бросить exception в нем?
_FR>>>Наверное, это было важно в первом релизе нового фреймворка, что бы сложными идиомами не отпугнуть армию индусов. С этой задачей, не спорю, Hashtable справилась.
L>>О каких сложных идиомах в случае Dictionary идет речь?
_FR>Об использовании TryGetItem
Ну если ты считаешь это сложной идиомой, пусть будет так.
_FR>>>А в "наследство" нам достались такие вот хитрости:
L>>Ну вот, то "не отпугнуть индусов", то "хитрости". Ты уж как-нибудь определись.
_FR>Я определён: "хитрости" могли бы "отпугнуть индусов".
Как-то не согласуется. С одной стороны ты говоришь, что проектировали для индусов. С другой — что есть "хитрости" которые могли бы "отпугнуть индусов".
Я так и не понял, напугали их или нет в итоге?
_FR>>>У меня сейчас нет под рукой Framework Design Guidelines, но, думаю, не сильно ошибусь, если предположу, что в ней советуют вместо ArrayList использовать List<object>, а вместо Hashtable Dictionary<object, object> (если более точные типы указать нельзя).
L>>Понятно, что List, а не ArrayList. Только это аргументом за то или иное поведение индексера ну никак не является.
_FR>Это к лову о том, почему я назвал Hashtable неудачно спроектированным контейнером
Здравствуйте, Lloyd, Вы писали:
_FR>>>>Ты реализацию Hashtable.get_Item видел? c Thread.Sleep внутри? А не думал, почему в System.Collections.Generic не сделали никакой поддержки многопоточности вообще? Hashtable пытались сделать суперпростой и суперфункциональной одновременно, что бы любой дурак понял, как ей пользоваться. L>>>Ссылочку на авторство этого высказывания дашь? _FR>>Какого именно? L>На то, что разработчики "пытались сделать суперпростой и суперфункциональной одновременно, что бы любой дурак понял, как ей пользоваться".
Это мой собственный вывод из того, что я вижу.
L>>>Да, кстати, как связаны дизайн контейнера и его реализация? Как-то не могу понять. _FR>>А так, что из плохого дизайна хорошую реализацию сложно сделать. L>Гм. Мы вроде как обсуждали поведение индексера. Что могло помешать им бросить exception в нем?
Этого я не знаю. Если интересно, могу выложить свои догадки.
_FR>>>>Наверное, это было важно в первом релизе нового фреймворка, что бы сложными идиомами не отпугнуть армию индусов. С этой задачей, не спорю, Hashtable справилась. L>>>О каких сложных идиомах в случае Dictionary идет речь? _FR>>Об использовании TryGetItem L>Ну если ты считаешь это сложной идиомой, пусть будет так.
Я видел с десяток парней с профильным образованием и опытом в несколько лет, которые педалили Hashtable несколько лет, потом пересели на дженерики, заметили, что те выбрасывают исключение и стали педалить так
Использовать TryGetValue отчего-то даже после намёка на это не получалось по-первой.
_FR>>>>А в "наследство" нам достались такие вот хитрости: L>>>Ну вот, то "не отпугнуть индусов", то "хитрости". Ты уж как-нибудь определись. _FR>>Я определён: "хитрости" могли бы "отпугнуть индусов". L>Как-то не согласуется. С одной стороны ты говоришь, что проектировали для индусов. С другой — что есть "хитрости" которые могли бы "отпугнуть индусов". L>Я так и не понял, напугали их или нет в итоге?
Я нигде не говорил, что "хитрости" "могли бы "отпугнуть индусов"." Я только сказал что "хитрости" есть, которые невооружённым индусским взглядом не заметишь.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
L>>Как-то не согласуется. С одной стороны ты говоришь, что проектировали для индусов. С другой — что есть "хитрости" которые могли бы "отпугнуть индусов". L>>Я так и не понял, напугали их или нет в итоге?
_FR>Я нигде не говорил, что "хитрости" "могли бы "отпугнуть индусов"." Я только сказал что "хитрости" есть, которые невооружённым индусским взглядом не заметишь.
А это наверное злой хакер написал, укравший твой парол? Вот ведь подлец!
Я определён: "хитрости" могли бы "отпугнуть индусов".
Здравствуйте, Lloyd, Вы писали:
L>>>Как-то не согласуется. С одной стороны ты говоришь, что проектировали для индусов. С другой — что есть "хитрости" которые могли бы "отпугнуть индусов". L>>>Я так и не понял, напугали их или нет в итоге?
_FR>>Я нигде не говорил, что "хитрости" "могли бы "отпугнуть индусов"." Я только сказал что "хитрости" есть, которые невооружённым индусским взглядом не заметишь.
L>А это наверное злой хакер написал, укравший твой парол? Вот ведь подлец!
L>Я определён: "хитрости" могли бы "отпугнуть индусов".
Ага, как обычно скатились к буквам
Можешь считать, что "хитрости" бывают первого и второго рада.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Можешь считать, что "хитрости" бывают первого и второго рада.
Ладно. Ты можешь просто и доходчиво объяснить, почему не-бросание исключения было ошибкой?
Не прибегая к индусам, синхронизации и неспособностям твоих коллег понять "сложные идиомы"?
Здравствуйте, Lloyd, Вы писали:
L>Ты можешь просто и доходчиво объяснить, почему не-бросание исключения было ошибкой?
Для начала: я пока нигде (в этом топике) не утверждал о том, что "не-бросание исключения было ошибкой". Мы стали спорить о том, что "стандартнее" и о том, что Hashtable: пример плохого, "непродуманного", контейнера. Вспомни своё сообщение
U>>Например, для Dictionary стандартное поведение это бросить исключение при обращении по несуществующему ключу,
_FR>Что это за стандарт? Зависит только от библиотеки.
Широко-распространенные бибилиотеки де-факто и задают стандарт.
За примером далеко ходить не надо: Hashtable из .Net Framework-а.
Я понимаю так: U>>>По стандарту надо бросить _FR>>Что это за стандарт? L>Hashtable
То есть это тебе с Undying спорить надо было, о том, чем же хороша и стандартна Hashtable. Я-то как раз хотел показать, что все делают по-разному (не факт, что хорошо, но — по разному).
Возвращаясь к нашим тараканам: теперь я скажу, что "не-бросание исключения было ошибкой", вернее, следствием ошибки проектирования Hashtable.
Дело не в "небросании", а целиком в том, что нельзя сразу и получить объект и узнать, что его там нету. Только двумя запросами. Это способствует тому, что во многих местах игнорируются ситуации, когда ключа, с которым код обратился к словарю в словаре не оказалось. В дизайне IDictionary<> надо всегда помнить, что нужного ключа может и не быть, а не то сразу получишь KeyNotFound. При дизайне Hashtable — ни о чём не говорящий NullReference.
Например, как выглядит код, который, при необходимочти возвращает данные из кэша:
(*) Главная проблем в том, что можно проверить, а можно и не проверить. И о том, что не проверил, ты узнаешь неизвестно где в самый неподходящий момент. Хорошее проектирование предполагает обраружение ошибки как можно ближе к месту её, ошибки, возникновения. IDictionary<> эту проблему решает на корню. Ошибиться так же можно и с ней, но результат будет совсем другой.
Дизайн IDictionary<> позволяет, при желании, работать по-старому:
И даже здесь удачно подобранное имя "хелпера" (выделено жирным) не позволяет "случайно забыть" о том, что же происходит. А вот на Hashtable так же производительно, как в IDictionary<> реализовать TryGetValue нельзя.
Лирическое отступление. Наболело много лет назад, пока не вышла первая бета дженериков, всвязи с чем болеть перестало, но сейчас разбередили
Как альтернатива TryGetValue, можно было бы либо
class Hashtable : …
{
public static readonly object NotFound = new object();
…
}
в геттере возвращать заместо null этот самый "special value" NotFound, что было бы уже лучше, но так же спорно. Можно было бы возвращать из индексера некий
struct Option
{
public bool HasValue { get; }
public object Value { get; }
}
но опять, же, ИМХО, TryGetValue выглядит приятнее.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Andrei F., Вы писали:
AF> AF>collection.EnsureItem(val) — ясно и однозначно понятно любому, кто знает английский
Могу предложить по крайней мере две трактовки:
1) аналог std::vector::at, в отличии от collection.Item, возможно являющегося аналогом std::vector::operator []
2) Выставляет этому элементу флажок уверенности в нём. Типа элементы бывают гарантированные и негарантированные...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, _FRED_, Вы писали:
_FR>Как альтернатива TryGetValue, можно было бы либо _FR>
_FR>class Hashtable : …
_FR>{
_FR> public static readonly object NotFound = new object();
Нафик нафик. Никак вон с DBNull размахаться не получается :)
_FR>[c#]
_FR>struct Option
_FR>{
_FR> public bool HasValue { get; }
_FR> public object Value { get; }
_FR>}
_FR>
Этот вариант уже вполне нормален, но в большинстве случаев синтаксически немножко более избыточен, чем TryGetValue. Оба этих варианта легко переходят один к другому при помощи простеньких статических хелперов.
... << RSDN@Home 1.2.0 alpha 4 rev. 1120 on Windows Vista 6.0.6001.65536>>