Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Java Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
 Очень много CompletableFuture  [new]
bob1970
Member

Откуда: Пермь
Сообщений: 204
На новом проекте встретил очень частое использование CompletableFuture. "Частое" это слабо сказано, почти сплошняком. Проект - типичный rest со spring внутри. CompletableFuture используется везде: в контроллерах, сервисах, репозиториях. Почти все методы возвращают или принимают CompletableFuture. Может это и нормально, но как-то непривычно.

Сообщение было отредактировано: 21 мар 20, 16:32
21 мар 20, 16:29    [22103584]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
bob1970
Member

Откуда: Пермь
Сообщений: 204
Уточнение. Почти все методы возвращают или принимают CompletableFuture/
21 мар 20, 16:32    [22103588]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
bob1970
Member

Откуда: Пермь
Сообщений: 204
Или это какой-то новый стиль программирования и все что касается работы с ресурсами (базы, файлы и т.п.) нужно делать через CompletableFuture.
21 мар 20, 16:47    [22103595]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
забыл ник
Member

Откуда:
Сообщений: 3241
bob1970
Или это какой-то новый стиль программирования и все что касается работы с ресурсами (базы, файлы и т.п.) нужно делать через CompletableFuture.

Все правильно, это пародия на функциональное программирование, но увы из-за долгой истории java эти концепты не получается сделать красиво и на мой взгляд код становится просто п..ц
21 мар 20, 17:17    [22103606]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 4508
bob1970,
Сабж служит для удобного асинхронного кодирования.
Вопрос, нужна ли асинхронность при БАНАЛЬНОМ REST?
Мое имхо - не нужна.
Платформа java и контейнер аппСервера сделали все чтобы прогер не задумывался о потоках и асинхронности.
21 мар 20, 18:48    [22103668]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
bob1970
Member

Откуда: Пермь
Сообщений: 204
PetroNotC Sharp
bob1970,
Сабж служит для удобного асинхронного кодирования.
...

Видел бы ты это удобно. Мозг в трубочку сворачивается. Представь себе код, где обычные объекты практически не используются, все завернуто в CompletableFuture. Я не против CompletableFuture. Все правильно. И удобно, и производительность. Но где грань применимости? Понятно что при обращении к внешним медленным ресурсам, и тогда получается что правильно запросы к БД нужно делать через CompletableFuture. Как-то бы определить эту границу.

Сообщение было отредактировано: 21 мар 20, 19:31
21 мар 20, 19:26    [22103685]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3531
bob1970
Все правильно. И удобно, и производительность. Но где грань применимости? Понятно что при обращении к внешним медленным ресурсам, и тогда получается что правильно запросы к БД нужно делать через CompletableFuture. Как-то бы определить эту границу.
В чем правильность-то? Со стороны производительности вообще не имеет никакого смысла переносить выполнение кода в другой поток, потому что как коду для выполнения нужен был поток, так и он и остался нужен, а накладные расходы при этом увеличиваются - контекст же еще нужно между потоками таскать.
21 мар 20, 19:47    [22103697]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
bob1970
Member

Откуда: Пермь
Сообщений: 204
Андрей Панфилов,

Удобно/неудобно. Размышляю пока. Почему выбрано такое решение. Вот пару ссылок:
CompletableFuture : A new era of asynchronous programming Сама статья ниочем, но заголовок внушает.

И другая
Synchronous or asynchronous, and why wrestle with wrappers?
Может и в самом деле ушла эра синхронного программирования.

Сообщение было отредактировано: 21 мар 20, 20:28
21 мар 20, 20:27    [22103718]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3531
bob1970
Может и в самом деле ушла эра синхронного программирования.
Нет, это просто нашли лоха-заказчика и выдали ему дичь за прорывную технологию.
Вот для просветления: Чем асинхронные сервлеты отличаются от Sping WebFlux
21 мар 20, 20:55    [22103724]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
mayton
Member

Откуда: loopback
Сообщений: 45514
bob1970,

мы-же кода не видели. Вполне возможно что существует кейс когда асинхронные микро-задачки
удобны. Как-по мне - не очень. Неудобно отслеживать статус ошибки. Если у тебя вся логика
- короткая и отбивается одним методом рест-контроллера - тогда ручная CompletableFuture - не
имеет смысла. Сам рест-контроллер и так обеспечивает множество конкурирующих сеансов.

Чтобы понять что CompletableFuture являлся ненужным обвесом - надо взять полностью этот
проект и переписать на классической rest архитектуре и просто посмотреть как оно вышло.
Возможно кода станет меньше.
21 мар 20, 20:58    [22103726]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
bob1970
Member

Откуда: Пермь
Сообщений: 204
mayton

мы-же кода не видели.

Там страшно. Очень.

mayton
Вполне возможно что существует кейс когда асинхронные микро-задачки
удобны.

Именно. Меня бы не смутили мелкие вставки, обращения к микро=задачкам. Но когда все. Сплошь. Маленький пример:
public interface IBaseRepository<TEntity, TFilter> {
    CompletableFuture<List<TEntity>> getRange(@NotNull TFilter filter);
    CompletableFuture<TEntity> getItem(@NotNull Object id);
    TEntity getItemReference(@NotNull Object id);
    CompletableFuture<List<TEntity>> getAll(@NotNull TFilter filter);
    CompletableFuture<Long> count(@NotNull TFilter filter);
    CompletableFuture<Void> update(@NotNull TEntity entity);
    CompletableFuture<Void> add(@NotNull TEntity entity);
    CompletableFuture<Void> remove(@NotNull TEntity entity);
    CompletableFuture<Void> update(@NotNull List<TEntity> items);
    CompletableFuture<List<TEntity>> add(@NotNull List<TEntity> items);
    CompletableFuture<Void> remove(@NotNull List<TEntity> items);
}

Это базовый репозиторий. Как можно понять все остальные репо-ии наследуются. Сервисы , контроллеры в том же духе. Ну и можете представить implementation.

mayton

Чтобы понять что CompletableFuture являлся ненужным обвесом - надо взять полностью этот
проект и переписать на классической rest архитектуре и просто посмотреть как оно вышло.
Возможно кода станет меньше.

Это нереально. Очень много кода.

В общем-то тему, наверное, нужно переименовать в Реактивная Java и закрыть. А решать каждый для себя.

Сообщение было отредактировано: 21 мар 20, 21:30
21 мар 20, 21:25    [22103737]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3531
bob1970,

а как при таком контракте репозитория хоть какую-то бизнес-логику организовать (ну банально: записать информацию о транзакции и списать сумму со счета)? или там CRUD и ничего больше?
21 мар 20, 21:33    [22103739]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 4508
bob1970
Видел бы ты это удобно.
я во второй части ответа как раз и выдвинул тезис, что это не удобно.
21 мар 20, 21:53    [22103743]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
mayton
Member

Откуда: loopback
Сообщений: 45514
Если рассмотреть такой упрощенный круд-реп

public interface IBaseRepository<TEntity, TFilter> {
    TEntity getItemReference(@NotNull Object id);
    CompletableFuture<Void> add(@NotNull TEntity entity);
}


И я допустим хочу с ним поработать. Я добавил документ entity.
И вызываю сраз-же getItemReference.

baseRepository.add(enity);
TEntity entity = getItemReference(entity.getId);

И во второй строке я получаю ошибку или исключение. Мой фьючерс еще не завершил работу.
Тоесть я видимо как-то не так работаю. Очевидно чтобы гарантировать что причинно-следственная
цепочка отработала я должен ставить искусственный барьер на первый и второй фьючерс.
И усложнять простой и очевидный код. И теперь вопрос. Ради чего это делалось?
И ведь это даже не CQRS. В той методике есть хотя-бы темпоральная хронология
в КОМАНДАХ. Команда которая дана раньше - раньше будет исполнена. Но только не здесь.

Почему нельзя было просто сделать так?

public interface IBaseRepository<TEntity, TFilter> {
    TEntity getItemReference(@NotNull Object id);
    void add(@NotNull TEntity entity);
}
21 мар 20, 21:56    [22103745]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
bob1970
Member

Откуда: Пермь
Сообщений: 204
Андрей Панфилов,
Примерно так:
    @Override
    public CompletableFuture<Void> add(@NotNull TEntity entity) {
        return CompletableFuture.runAsync(() -> {
            EntityManager entityManager = factory.createEntityManager();
            try {
                EntityTransaction transaction = entityManager.getTransaction();
                try {
                    transaction.begin();
                    entityManager.persist(entity);
                    transaction.commit();
                } catch (Exception ex) {
                    transaction.rollback();
                    throw ex;
                }
            } catch (Exception ex) {
                LOGGER.error(this.getClass().getName() + " add item error ", ex);
                throw ex;
            } finally {
                entityManager.close();
            }
        }, executor);
    }


И повторюсь -там не только CRUD. Там ВСЕ. Вообще ВСЕ. Сервисы с бизнес-логикой, контроллеры и прочий код. Все на future
21 мар 20, 21:58    [22103746]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
bob1970
Member

Откуда: Пермь
Сообщений: 204
PetroNotC Sharp,
Сравни
class Synchronous {
    // I/0 operations: blocking, synchronous
    <T> T fetchFromDb(Class<T> entityClass, long id) { return null; }
    String sendHttpGet(String url) { return null; }
    void sendEmail(String to, String content) { }

    // the business logic: synchronous
    void runBusinessProcess() {
        User user = fetchFromDb(User.class, 42);
        String profile = sendHttpGet(
            "http://profile_service/get/" + user.getProfileId());
        sendEmail(user.getEmail(), "Your profile is: " + profile);
    }
}


и

class Wrappers {
    // I/O operations: non-blocking, asynchronous
    <T> CompletableFuture<T> fetchFromDb(Class<T> entityClass, long id) { return null; }
    CompletableFuture<String> sendHttpGet(String url) { return null; }
    CompletableFuture<Void> sendEmail(String to, String content) { return null; }

    // the bussines logic: asynchronous
    CompletableFuture<Void> runBusinessProcess() {
        // thenCompose: also known as flatMap, combines two futures
        return fetchFromDb(User.class, 42).thenCompose(user -> {
            // storing the intermediate result in variables
            CompletableFuture<String> httpResult = 
              sendHttpGet("http://profile_service/get/" + user.getProfileId());
              
            return httpResult.thenCompose(profile ->
                    sendEmail(user.getEmail(), "Your profile is: " + profile));
        });
    }
}


Это отсюда

Сообщение было отредактировано: 21 мар 20, 22:08
21 мар 20, 22:07    [22103750]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
mayton
Member

Откуда: loopback
Сообщений: 45514
Как будто-бы калька с другого фреймворка. Может даже не на Java а на другом языке или технологии
где такие штуки красиво заворачиваются в аспекты или лябды. Здесь как-бы мясо вот серединке

transaction.begin();
entityManager.persist(entity);
transaction.commit();

А сверху и снизу просто одинаковые обёртки которые обеспечивают трансфер in/out параметров.
Вот почему мне и напомнило аспекты.
21 мар 20, 22:08    [22103752]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
bob1970
Member

Откуда: Пермь
Сообщений: 204
mayton,

Да, это главное. Но как завернуто
return CompletableFuture.runAsync(() -> {
...
 }, executor);
21 мар 20, 22:11    [22103754]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3531
bob1970

Примерно так:
    @Override
    public CompletableFuture<Void> add(@NotNull TEntity entity) {
        return CompletableFuture.runAsync(() -> {
            EntityManager entityManager = factory.createEntityManager();
            try {
                EntityTransaction transaction = entityManager.getTransaction();
                try {
                    transaction.begin();
                    entityManager.persist(entity);
                    transaction.commit();
                } catch (Exception ex) {
                    transaction.rollback();
                    throw ex;
                }
            } catch (Exception ex) {
                LOGGER.error(this.getClass().getName() + " add item error ", ex);
                throw ex;
            } finally {
                entityManager.close();
            }
        }, executor);
    }
Это же реализация репозитория, причем посредственная, я же спрашивал как организовать бизнес-логику, когда нужно два репозитория использовать.
21 мар 20, 22:11    [22103755]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
bob1970
Member

Откуда: Пермь
Сообщений: 204
Андрей Панфилов,
Примерно так
        CompletableFuture task1 = callService1(context);
        CompletableFuture task2 = callService2(context);

        return CompletableFuture
            .allOf(task1, task2)
            .thenCompose(nop -> callService3(context))
            .thenApply(nop -> callService4(context)).getResult());
21 мар 20, 22:15    [22103757]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3531
bob1970
Примерно так
        CompletableFuture task1 = callService1(context);
        CompletableFuture task2 = callService2(context);

        return CompletableFuture
            .allOf(task1, task2)
            .thenCompose(nop -> callService3(context))
            .thenApply(nop -> callService4(context)).getResult());
А на ACID забить?
21 мар 20, 22:18    [22103758]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
bob1970
Member

Откуда: Пермь
Сообщений: 204
Андрей Панфилов
А на ACID забить?

Оххх... Там до таких страшных слов, как до Китая.
А вообще, я не про конкретный проект. Я про подход. Реактивная Java есть и используется. И похоже использовать ее нужно как-то так. Короче, надо изучать это дело.

Сообщение было отредактировано: 21 мар 20, 22:27
21 мар 20, 22:24    [22103760]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
bob1970
Member

Откуда: Пермь
Сообщений: 204
mayton

Почему нельзя было просто сделать так?

public interface IBaseRepository<TEntity, TFilter> {
    TEntity getItemReference(@NotNull Object id);
    void add(@NotNull TEntity entity);
}


Это самый главный вопрос.
21 мар 20, 22:32    [22103761]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
andreykaT
Member

Откуда:
Сообщений: 2720
bob1970
Или это какой-то новый стиль программирования и все что касается работы с ресурсами (базы, файлы и т.п.) нужно делать через CompletableFuture.

ты прям плей фреймворк описал ))) в нем тоже все возвращает футуры. все что связано с взаимодействием со сторонними сервисами или ресурсами (бд, веб, акторы и тп)
22 мар 20, 00:31    [22103795]     Ответить | Цитировать Сообщить модератору
 Re: Очень много CompletableFuture  [new]
andreykaT
Member

Откуда:
Сообщений: 2720
bob1970
PetroNotC Sharp
bob1970,
Сабж служит для удобного асинхронного кодирования.
...

Видел бы ты это удобно. Мозг в трубочку сворачивается. Представь себе код, где обычные объекты практически не используются, все завернуто в CompletableFuture. Я не против CompletableFuture. Все правильно. И удобно, и производительность. Но где грань применимости? Понятно что при обращении к внешним медленным ресурсам, и тогда получается что правильно запросы к БД нужно делать через CompletableFuture. Как-то бы определить эту границу.

дело привычки. мозг перестает скручиваться в трубку если ты постоянно тащишь все через функторы монады (мап флатмап или зенкомпос зенаплай вроде). да. это асинхронка, но вот мне лично кажется, что в этих кишках ошибки ловить прям отдельный челлендж. особенно когда проблемы возникают с многопоточкой. а они возникают. кто говорит нет - тот обманывает.

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

Сообщение было отредактировано: 22 мар 20, 00:35
22 мар 20, 00:34    [22103796]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
Все форумы / Java Ответить