Обновить
3

Уверенный пользователь холодильника

1
Подписчики
Отправить сообщение
Есть статистически подтвержденные выводы?
Потому что сразу после рождения дети в принципе еще не умеют тянуться.

Я это уже постил здесь в комментариях, потому скопирую оттуда.


Есть вот такое исследование, там, как я понимаю, есть статистически значимые различия в предпочтениях к игрушкам с самого раннего возраста. Это не может объясняться давлением социума в таком "нежном" возрасте.


https://www.pitt.edu/~bertsch/Todd_et_al-2016-Infant_and_Child_Development.pdf


И версия того же самого глазами изнасилованных журналистов:


https://digest.bps.org.uk/2016/06/03/infants-show-a-preference-for-toys-that-match-their-gender-before-they-know-what-gender-is/

Приведите пример их нужности

Я могу попробовать. Как вы заметили, лямбды — это очень явный и понятный пример частного случая интерфейса, в котором только один метод. Они (интерфейсы) в принципе делаются для удобства написания и работы некоего "библиотечного" кода, который будет в оговорённом порядке вызывать методы из контракта/интерфейса и ожидать отклика тоже в соответствии с контрактом оного интерфейса — с точки зрения такого кода нет абсолютно никакой разницы, что именно находится по другую сторону.
Один из самых явных примеров здесь — коллекции в Java (и я ничуть не сомневаюсь, что вы сможете коллекции переписать лучше, там немало спорных решений), где есть установленный контракт для каждой коллекции, в том, что она поддерживает три операции — может сообщить собственный размер, сообщить, является ли X одним из её элементов, и вернуть Iterator, который перечислит все элементы в некотором (явно неопределённом) порядке. И ваш код может работать как с ArrayList, так и с HashMap$EntrySet вообще без изменений, до тех пор пока он вызывает только методы из контракта Collection<T>. Например, чтобы написать код, который примет на вход коллекцию и предикат и вернёт списком все элементы коллекции, которые предикат (не)прошли, вы можете либо перегрузить метод и для каждой реализации Collection написать один и тот же код (попутно создав себе работы на будущее, когда кто-нибудь напишет ещё одну реализацию коллекции) — либо воспользоваться интерфейсами, и написать это один раз. Какой вариант будет короче — думаю, очевидно. Какой из них будет лучше — можно весьма долго дискутировать, у разных людей разные мнения.

Прикинул сейчас к своему вялотекущему занятию по обустройству одной из стен в квартире под кинопроектор — и получается, что с учётом той диагонали (~3,89 м) и проектора с разрешением Full HD зернистость картинки будет незаметна только если сидеть почти вплотную у противоположной стены — расстояние получается пять метров с небольшим, а с учётом размеров комнаты (5.6 м) «допуск» выходит всего лишь полметра.

Весьма интересно.
Пусть даже материалы — в этом случае, в аналогии с сантехникой, фокус с гаечных ключей смещается на сами гайки. Тут по традиции bikeshedding'а находится уже намного больше желающих подсказать, но станете ли вы сильно возражать против идеи, что на самом деле требования от бизнеса к программисту лучше выразить на намного более высоком уровне, чем список из «одобренных технологий», который программистам передаёт человек, для которого это всё зачастую пустой набор символов сам по себе, зато он слышал, что у соседей тоже гайки с напылением сплава цинка с вольфрамом и изнутри по всей длине труб идёт тонкая полоса из серебра, для очистки воды от микробов?

Что до стоимости будущей поддержки — даже самим программистам оценить зачастую нереально, но вот конкретно по этому параметру большинство ныне модных технологий будут не на первых местах, т.к. в первую очередь они заточены на уменьшение Time To Market, а после хоть трава не расти. Отсюда и вытекает мой тезис выше, что бизнес на самом деле™ не волнует будущая поддержка и всё из этой оперы.
А я вот считаю, что бизнесу не должно быть никакого дела, какими инструментами пользуются исполнители. Насколько я понимаю, почти никто не контролирует, каким набором ключей сантехник будет затягивать гайки — и это нормально, так и должно быть.

Впрочем, здесь проблема больше не в том, что кто-то пытается продвигать неподходящие под задачу инструменты — здесь скорее ситуация, когда сначала для того, чтобы занять рынок, бизнесмены всегда ставят жесткие сроки, и в результате что бы ни писали программисты — получится не более чем прототип. А как только рынок занят — бизнес перестаёт шевелиться, открывает пасть и почивает на лаврах, а на исправление прототипа средств не выделяет — мол, работает — не трожь. На UX, фактически, просто всем наплевать — но и пользователи тоже хороши, так как очень мало голосуют ногами к конкурентам (отчасти ещё и потому, что у конкурентов зачастую тот же прототип, но ещё хуже, ведь недаром они не на первом месте). Круговорот, в общем.
Программисты все меньше влияют на развитие IT

И это печально — неспециалист не может сделать ничего хорошего в узкоспециальной области в долгосрочной перспективе (в краткосрочной — может, но обычно случайно).

Уметь-то умеют, но инфраструктура в целом сейчас движется к уменьшению пауз GC — так что надеяться на очистку внутри STW решение не очень хорошее, потому что STW в идеале наступать не должен никогда.

Я вроде бы где-то читал, что работа над строками по-прежнему идёт. Вот в 9 версии, к примеру, сделали компактификацию в смысле перекодирования в LATIN-1 если в строке находятся только совместимые символы — это уже должно уменьшить потребление по меньшей мере процентов на 20, иногда на 40. Следующим этапом, вроде бы, должна стать замена эквивалентных char[] в разных строках.
Может быть, когда-нибудь и доживём до триумфального возвращения шаренных массивов. Но однозначно не в виде STW-обработки, и не в ближайшие два-три года. Пусть сначала Coin и Loom закончат.
Альтернативой может стать усложнение GC по отношению к строкам — тогда можно сохранить внутреннее представление в виде ссылки на родительский элемент, но при этом ссылка на родителя не должна препятствовать его сборке GC — и при сборке демон должен будет прозрачно заменить ссылку+оффсеты на функционально и логически эквивалентный «настоящий» массив, полученный в результате слайса.

В Java такое сделать проблематично из-за строгости реализации — при таких операциях GC должен иметь эксклюзивный доступ к объекту, чтобы другие потоки не могли увидеть её в неконсистентном состоянии (а они могут, т.к. массив и оффсеты это три операции записи, причём в несинхронизированые поля, которые ещё и синхронизировать нельзя из соображений производительности). Это подразумевает чуть ли не подмену значения по всем ссылкам, которая должна быть полностью незаметна для всего пользовательского кода, и прочие весёлости, вроде следующей из такого требования двойной индирекции в самих указателях. В общем, проще деоптимизировать и вернуться к проблеме если она станет совсем уж невыносимой.

Рискну предположить, что в JS подобные трюки проворачивать всё же проще, так что вдруг у V8 получится.
К слову, как раз про пароли и фейсбук я вполне могу поверить — Цукерберг сам неоднократно говорил, что слепил сайт «из того, что было» и палок. Если там хоть что-то осталось от решений того времени (а учитывая общую культуру разработки с лозунгом «технический долг — это проблема будущих поколений» — осталось, и ещё как), то пароли открытым текстом я считаю закономерным явлением.
А в чём, по-вашему, различия между, скажем, программистами и писателями?

Сегодня у них разве что текстовые редакторы разные (у программистов более продвинутые, но это необходимость). Но и те, и другие пишут тексты на компьютерах, озабочены читаемостью своих текстов и их выразительностью.
Ну да, программные код никто не издаёт распечатанными в подарочных изданиях, но это следствие иной целевой аудитории, и только.
А есть ли люди, которые в проде используют Java выше 8

В нашем проекте главная ветка уже перешла на 11, и идут работы по переходу на 12. Мы делаем именно релизы, так что это пока что не прод, но всё к тому движется.


Откуда вы ее берете?

Глянул сейчас — похоже, что таки у Oracle, с jdk.java.net, но версию именно OpenJDK. Про патчи — вот честно, понятия не имею, насколько скоро. Прошу за это прощения. В настоящее время версия с сайта датируется 19м марта 2019, но мне неизвестно, есть ли там сейчас какие-то критические проблемы. Замечу, впрочем, что Java теперь в основном open-source — и, следственно, с патчами будет как там принято. Но есть и платные дистрибутивы, там наверняка можно будет по контракту с кого-нибудь стрясти заплатку в экстренном режиме.

В GraphQL резолвер может вернуть Promise

А на вход он может принять коллекцию вместо одного объекта? Если нет — то выходит, что новая крутая технология в очередной раз способствует уменьшению производительности клиентских приложений. Потому что если вы посмотрите хорошо на мой вопрос — конкретно на то, что я цитировал — то выходит, что GraphQL на вложенных запросах как раз задыхается. Во-первых, потому, что в исходной цитате нету никакой проекции — значит это, что мы читаем всё, а умный GraphQL потом выбрасывает прочитанное? Но мне не нужен целый GraphQL чтоб из объекта свойства поудалять, понимаете? Или же в статье всё-таки представили технологию без раскрытия реальных киллер-фич? Во-вторых, если не пользоваться хаками EventLoop'а, как это делают в DataLoader — читать предлагается строго по одному элементу, чего я ну никак не ожидаю от действительно зрелой технологии, заточенной на оптимизацию доступа к данным.
Смотрите. Если при запросе


flavors {
  id
  name
  description
  nutrition {
    id
    sodium
  }
}

В процессе выполнения какая-нибудь подсистема получит внутренний запрос в виде


nutrition(id: $.flavors.id) { /*это JSONPath такой, надеюсь суть ясна*/
   id
   sodium
}

То я возражать не буду — многие так сделают, решение неидеальное, зато гибкое. А если такого нет, и грузить буду по одному nutrition, то последует мой вывод — "съешь ещё этих мягких калифорнийских фреймворков да выпей смузи, а клиенту скажем оперативы побольше купить".

Dataloader'ом легко оборачивать и соединять разные источники данных (кэш, search engine, база, web-service)

Фактически, это значит, что в кэше можно хранить данные из нескольких функций — и это уже не такое же смелое заявление, как в исходной форме.
У меня, к слову, вот такой DataLoader-подобный кеш на промисах в проекте крутится в одном-двух компонентах — как жаль, что я не фейсбук и пиарить свои isFunction так же хорошо не умею, ведь про мой кеш даже в моём проекте мало кто знает.


в отличие от ORM

Назначение ORM — оградить бизнес-логику от знаний, как именно хранятся данные. Поэтому, достаточно развитые ORM позволяют точно так же объединять разные источники данных — с вас потребуется только определение PersistenceUnit'а (переводчика из диалекта QCRUD ORM на диалект, нативный для Store). И работать будет уже не только для загрузка, но и запись.


Выглядит примерно как по ссылке ниже. Ограничения, по сути, те же самые, что у вашего DataLoader'а — N + M(>=N) запросов для чтения, при записи всплывает поддержка распределённых транзакций, что есть не у всех Store'ов. Но у модной нынче модели EventualConsistency и транзакций-то, по сути, нет, так что это вроде как уже не большой минус.
https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Composite_Persistence_Units

Flavor: {
  nutrition: (parent) => {
    return mongodb.collection('nutrition').findOne({
        flavorId: parent.id,
    });
  }
}

findOne

Жуть какая. А можно там как-то сделать поиск по nutrition для списка родительских объектов? Чтобы было не 1+M запросов, а ну хотя бы два?

нельзя распарсить 2012-11-30 в LocalDateTime

Логично — ведь в строке не указано время, и не бывает "времени по умолчанию". У вас там дата — значит, работать надо с датой, LocalDate. Это, к слову, намного удобнее чем работать с "моментом, указывающим на начало дня, в базе он хранится как UTC, а клиенту надо будет показать тоже начало дня, но в его часовом поясе, смотри не перепутай".


То же самое с OffsetDateTime — какой часовой пояс вы предлагаете считать "поясом по умолчанию"? Если пояс сервера — юзайте LocalDateTime сразу. Статически задать пояс нельзя пока "Europe/Moscow" означает два или более разных сдвига в зависимости от хотелок политиков.


Я наоборот назову это более хорошим дизайном API — вы сразу знаете, что вы дали на вход и что вы получите в качестве результата. Не как раньше, где в принципе не было понятия каледнарной даты, нельзя было никак выразить требование "каждые два дня в 19:16", а Calendar.getInstance() мог вернуть вам буддийский календарь, и ничего вы с этим просто так не поделаете — сколько кода вы видели, который пишет new GregorianCalendar()?


А ваша проблема действительно решается "донастройкой парсера", и это делается один раз, в утилите:
Либо


var staticFormatter = new DateTimeFormatterBuilder()
    .append(DateTimeFormatter.ISO_DATE)
    .appendOptional(DateTimeFormatter.ISO_TIME)
    .parseDefaulting(ChronoField.NANO_OF_DAY, 0)
    .toFormater();

staticFormatter.parse("2012-11-30", LocalDateTime::from);

new DateTimeFormatterBuilder()
    .append(staticFormatter)
    .parseDefaulting(ChronoField.OFFSET_SECONDS,
//помните, что offset_seconds зависит от "сейчас"?
        ZoneId.systemDefault()
        .getRules()
        .getOffset(Instant.now())
        .get(ChronoField.OFFSET_SECONDS)
    ).parse("2012-11-30", OffsetDateTime::from);

Либо, раз уж так охота не знать, пользуетесь вы форматом для даты, момента или локального момента:



DateTimeFormatter.ofPattern(externalPattern)
    .parseBest(dateString,
        OffsetDateTime::from,
        parsed -> LocalDateTime.from(parsed)
            .atZone(ZoneId.systemDefault())
            .toOffsetDateTime(),
        parsed -> LocalDate.from(parsed)
            .atStartOfDay(ZoneId.systemDefault())
            .toOffsetDateTime()
    );
transform() — Применяет предоставленную функцию к строке. Результат не должен быть строкой.

Подчёркнутое — ошибка. Результат может не быть строкой, но может и быть.


Strign foobar = "foo".transform(s -> s + "-bar");

является полностью "легальным" использованием.


Так же как и


char[] chars = "foo".transform(s -> s.chars().filter(c -> c >= 103).toArray());
Что за странная избыточность с локализацией значений? Это нормально для подобных баз данных? Какие есть полезные эффекты в таком отсутствии нормализации?

У меня, честно говоря, никогда не стоит прямо задачи "используй экземпляр этого класса потокобезопасно" (разве что в каком-нибудь тесте) — как правило, требование более высокое — "у нас неправильно форматируется время в час пик, почини".


Кстати, для именно более высоко сформулированной задачи в Java7 Joda тоже будет решением, потому что умеет вот так: DateTimeFormatter::print(long millisecond-instant)
— а значит без проблем работает где-нибудь в виде метода-утилиты, и не будет заставлять вас отказываться от использования Calendar'ов в API.


в йоде по удобству АПИ есть сложные моменты

Расскажите про это подробнее.

Это в каком именно методе происходит?

Да вот в этом. Я вам точно говорю — снаружи синхронизировать будет куда проще.


Красивый пример. Но очень простой

Ну у меня не настолько хорошая фантазия или богатый опыт хаков JDK, чтобы я сходу могу придумывать сложные примеры. Впрочем и цели такой не было — показать что-то сложное. Основная идея как раз в том, что расширять типы из JDK — не сложно. По крайней мере, для доброй части типов.

Теперь есть ещё четвёртое решение — пользоваться чем-то более приятно написанным, чем старые DateTime-части JDK. Например, потокобезопасным форматтером:


  static DateTimeFormatter formatter = ...?profit

  public static String formatMyTime(Date date) {
    ZonedDateTime zdt = date.toInstant()
        .atZone(formatter.getZone());
    return formatter.format(zdt);
  }

В отсутствие Java8 можно "перебиваться" Joda. Если хочется совсем упороться — то взять Time4J.

Информация

В рейтинге
Не участвует
Откуда
Россия
Зарегистрирован
Активность