Так про то и речь, рефлекшены — это костыль для крайних случаев, и программисты (обычно) это понимают. А «штатными» средствами, считаю, не должно быть даже потенциальной возможности всё испортить. То есть, приведения типов MutableList <-> ImmutableList просто скомпилироваться не должны.
2) Ваша реализация похожа на грабительство — Вы отбираете массив у вызывающего объекта. Это антипаттерн.
Обоснуете, почему «анти»? Например, из ORM вы получили ArrayList<MyEntity>, понимаете, что меняться он не будет, и хотите дальше в своём коде использовать его как ImmutableList<MyEntity>. Преобразовали, старый список ушёл, новый появился. Чем плохо?
3) На самом деле, ImmutableList-ы в большинстве библиотек построены на основе сбалансированных деревьев, поэтому, изменение листа проходит за O(log(N)).
Вот это вообще не понял. Какие изменения ImmutableList-а?
4) Вы придумали кривой велосипед, который никто в здравом уме не примет за стандарт.
Кривой он только тем, что использует рефлекшены (если вдруг поменяют название поля ArrayList#elementData — поломается). Естественно, если бы это делали авторы Java, можно было бы без рефлекшенов обойтись.
Да, получается не полностью иммутабельный объект, а иммутабельный список потенциально мутабельных объектов (как в определениях исходной статьи).
Получить «иммутабельный список иммутабельных объектов» — задача интересная, но вряд ли на Java решаемая. Хотя если в списке лежат только голые данные в виде POJO, то можно было бы сделать для них иммутабельные копии через рефлекшены. Но это очень долго и уже поэтому не нужно.
В Java для такого есть готовый Collections.unmodifiableList. Просто он для такой ситуации ничем не лучше, чем по-настоящему immutable список (если последний достаточно быстрый). Зато с immutable взаимные ожидания методов более явно задекларированы. Хотя возможны и ситуации, когда immutable не подходит — как раз когда изменяемость нужна — вызываемый метод не может менять список, но знает, что его может менять вызывающий метод, и умеет это обрабатывать. Но это отдельные случаи, редкие и неприятные как раз необходимостью этой особой обработки.
Ну это понятно, что по возможности стоит избегать. Но согласитесь, что привычный к написанию equals программист обычно воспринимает каст гораздо менее болезненно, чем рефлекшены.
Бывают неприятные случаи, когда приходится хакать. Для этих случаев есть рефлекшены. Но к ним обычно и отношение соответствующее: «это ружьё рано или поздно стрельнёт в ногу». А приведение типов — вполне штатная операция, выполняемая на каждом углу, её легко можно написать, не особо задумываясь или «временно для тестов, потом поправлю». И когда код читаешь, оно не особо в глаза бросается. А если уж сначала UnmodifiableList станет, например, переменной типа Object (всякое в жизни бывает), то в другом месте кастинг в List будет выглядеть вообще абсолютно невинно.
Если, как предложено в статье, List является наследником UnmodifiableList, то получим ту же проблему, что в начале статьи описана: в API на входе UnmodifiableList, вызывают его с экземпляром List, тогда реализация API внутри может спокойно сделать приведение типов к List и менять, что захочет. Альтернативы — либо копирование, либо обёртка (как сейчас и сделано в Collections.unmodifiableList()). В обоих случаях оверхеда не избежать. Обёртка на первый взгляд кажется меньшим оверхедом, но если вспомнить про сборку мусора, то разница может оказаться совсем небольшой.
Сомневаюсь в полезности UnmodifiableList в случае наличия ImmutableList. В вашем примере: public UnmodifiableList<Agent> teamRoster() — вот получили список, начали его на экран выводить, а он в это время поменялся из другой нити. Единственный вариант придумался, когда нужен именно UnmodifiableList без «стрельбы в ногу» — метод, циклически опрашивающий объекты на предмет какого-то события (пропустили один объект — ничего, на следующем цикле опросим; опросили один объект два раза за цикл — тоже ничего).
А вот что мешает изготовить свой ImmutableList и использовать в своих проектах? Не обязательно же всю экосистему менять. Получили от библиотеки List — скопировали сразу же содержимое в свой ImmutableList и дальше его гоняете. Лишнее копирование неприятно, но без него не обойтись.
Да, абсолютно так — проще и дешевле. Потому я и не особо верю в воспитание критичного мышления. В теории это было бы здорово, а на практике — гос властям это не нужно (пропаганда выгоднее), людям тоже зачастую проще не думать лишнего, а принять чью-то точку зрения. В итоге из хорошей идеи получится либо ничего, либо воспитание чего-то совсем другого.
Если уж обобщать понятие эволюции в эту сторону, то можно говорить об эволюции идей (в том числе, политических). А вот к обществу понятие эволюции вряд ли применимо. Да и «общество в целом» — слишком растяжимое понятие. Что это — мой город? всё человечество? государство? совокупность всех моих френдов в соцсети? Если же вернуться к военным примерам («общество = одна из противоборствующих сторон»), то помимо более-менее ясного и определённого случая Великой Отечественной можно вспомнить ещё Гражданскую войну, войну СССР в Афганистане и т.д. Там всё не так просто с «проиграет и сгинет в истории».
Насчёт «ограничивать Интернет и информацию вообще — неправильно» полностью согласен. А вот мысль про «правильнее воспитывать в людях культуру потребления этой информации» очень сомнительная. Она подразумевает, что есть кто-то знающий «как правильно», который будет навязывать другим своё мнение. Фактически, предлагаете заменить цензуру на самоцензуру. «Пастернака не читал, но осуждаю».
Только с точки зрения эволюции выбор выглядит совсем не так. «Выигрывает» не кидающийся на амбразуры, а сумевший эффективно дезертировать / отсидеться в тылу / и т.п., после чего завести потомство и тем самым размножить свой генотип. Здравствуй, социал-дарвинизм!
Только вот выглядит это всё слишком низменно и примитивно. Людям (обычно) хочется верить, что они не просто машина для бессмысленного воспроизводства генов. А из этой веры возникает и «место подвигу», и «ценности западного общества».
«Как в Германии» тоже работать не будет. Посыпятся штрафы — люди уйдут в более безопасные сети (для торрентов, например, I2PSnark есть, правда, я его не пробовал).
То, что цитату высказал какой-то уважаемый человек, не делает её автоматически справедливым высказыванием. Лично мне данная цитата больше нравится именно в сокращённом варианте.
Такое впечатление, что у Франклина вообще проблемы с развёрнутыми цитатами. Взять хотя бы знаменитое «время — деньги». В оригинале оно звучит как-то так: «Помни, что время — деньги; тот, кто мог бы ежедневно зарабатывать по десять шиллингов и тем не менее полдня гуляет или лентяйничает дома, должен — если он расходует на себя всего только шесть пенсов — учесть не только этот расход, но считать, что он истратил или, вернее, выбросил сверх того ещё пять шиллингов». Как по мне, гораздо более занудно, тоскливо и меркантильно-приземлённо, чем короткий вариант, который каждый читающий наполняет отчасти своими смыслами.
Если цена сообщения в ADM фиксирована, то при падении курса могут ноды начать разбегаться (место под хранение сообщения стоит дороже, чем получаемая за сохранение сообщения сумма), а при росте курса станет очень дорого отправлять сообщение, и поэтому начнут разбегаться уже потребители. Разве нет?
сеть определяет порядок, кто из делегатов сети формирует следующий блок
Ой, почитал, всё не просто там получается. Т.е. не каждая нода участвует в генерации блокчейна, а только 101 с наибольшим количеством ADM (из изъявивших желание)? Получается, у остальных нодовладельцев финансовой мотивации держать ноду нет?
Есть реализации этой штуки на всех языках программирования
В репозитории ничего сишного не нашёл…
Не верю в киллер-фичи
Мессенджер — такое ПО, которым не будешь пользоваться в одиночку. И тяжело обосновать постороннему человеку, почему именно в этом мессенджере следует переписываться. Как следствие, мессенджер не выйдет из ниши (утрируя) «нечто для кучки гиков и террористов».
(Хотя после этого пришла и мрачная мысль: в ReactOS «еще результативнее» может значить, что раньше загрузка падала на 70%, а теперь на 90%)
ArrayList<MyEntity>
, понимаете, что меняться он не будет, и хотите дальше в своём коде использовать его какImmutableList<MyEntity>
. Преобразовали, старый список ушёл, новый появился. Чем плохо?Вот это вообще не понял. Какие изменения ImmutableList-а?
Кривой он только тем, что использует рефлекшены (если вдруг поменяют название поля
ArrayList#elementData
— поломается). Естественно, если бы это делали авторы Java, можно было бы без рефлекшенов обойтись.Получить «иммутабельный список иммутабельных объектов» — задача интересная, но вряд ли на Java решаемая. Хотя если в списке лежат только голые данные в виде POJO, то можно было бы сделать для них иммутабельные копии через рефлекшены. Но это очень долго и уже поэтому не нужно.
Collections.unmodifiableList
. Просто он для такой ситуации ничем не лучше, чем по-настоящему immutable список (если последний достаточно быстрый). Зато с immutable взаимные ожидания методов более явно задекларированы. Хотя возможны и ситуации, когда immutable не подходит — как раз когда изменяемость нужна — вызываемый метод не может менять список, но знает, что его может менять вызывающий метод, и умеет это обрабатывать. Но это отдельные случаи, редкие и неприятные как раз необходимостью этой особой обработки.List
является наследникомUnmodifiableList
, то получим ту же проблему, что в начале статьи описана: в API на входеUnmodifiableList
, вызывают его с экземпляромList
, тогда реализация API внутри может спокойно сделать приведение типов кList
и менять, что захочет. Альтернативы — либо копирование, либо обёртка (как сейчас и сделано вCollections.unmodifiableList()
). В обоих случаях оверхеда не избежать. Обёртка на первый взгляд кажется меньшим оверхедом, но если вспомнить про сборку мусора, то разница может оказаться совсем небольшой.public UnmodifiableList<Agent> teamRoster()
— вот получили список, начали его на экран выводить, а он в это время поменялся из другой нити. Единственный вариант придумался, когда нужен именно UnmodifiableList без «стрельбы в ногу» — метод, циклически опрашивающий объекты на предмет какого-то события (пропустили один объект — ничего, на следующем цикле опросим; опросили один объект два раза за цикл — тоже ничего).А вот что мешает изготовить свой ImmutableList и использовать в своих проектах? Не обязательно же всю экосистему менять. Получили от библиотеки List — скопировали сразу же содержимое в свой ImmutableList и дальше его гоняете. Лишнее копирование неприятно, но без него не обойтись.
Современная двухсекундная — это про что речь?
Насчёт «ограничивать Интернет и информацию вообще — неправильно» полностью согласен. А вот мысль про «правильнее воспитывать в людях культуру потребления этой информации» очень сомнительная. Она подразумевает, что есть кто-то знающий «как правильно», который будет навязывать другим своё мнение. Фактически, предлагаете заменить цензуру на самоцензуру. «Пастернака не читал, но осуждаю».
Только вот выглядит это всё слишком низменно и примитивно. Людям (обычно) хочется верить, что они не просто машина для бессмысленного воспроизводства генов. А из этой веры возникает и «место подвигу», и «ценности западного общества».
Такое впечатление, что у Франклина вообще проблемы с развёрнутыми цитатами. Взять хотя бы знаменитое «время — деньги». В оригинале оно звучит как-то так: «Помни, что время — деньги; тот, кто мог бы ежедневно зарабатывать по десять шиллингов и тем не менее полдня гуляет или лентяйничает дома, должен — если он расходует на себя всего только шесть пенсов — учесть не только этот расход, но считать, что он истратил или, вернее, выбросил сверх того ещё пять шиллингов». Как по мне, гораздо более занудно, тоскливо и меркантильно-приземлённо, чем короткий вариант, который каждый читающий наполняет отчасти своими смыслами.
В репозитории ничего сишного не нашёл…
Мессенджер — такое ПО, которым не будешь пользоваться в одиночку. И тяжело обосновать постороннему человеку, почему именно в этом мессенджере следует переписываться. Как следствие, мессенджер не выйдет из ниши (утрируя) «нечто для кучки гиков и террористов».