Notes about Java 🌴
197 subscribers
41 photos
1 video
3 files
76 links
vk.com/notes_about_java
Научим программировать с нуля!
1. Видео на практике в коде
2. Краткие по времени
3. Очередной урок только на пройденном
4. Понятные аналогии
5. Можно скачать код занятий
@max_urusoff
Download Telegram
#forkjoinpool

Конкретно в текущем проекте, где я работаю, этот вид threadpool используется для параллельной обработки порций данных.

Надо сказать, что справляется со своей задачей хорошо. Были сделаны сравнения с классическим fixedThreadPool. В результате тестов под настоящей нагрузкой forkjoin подход первым прорвал линию фронта и отработал без ошибок.

В чем сила??
В нем воровская технология отбирания задач у соседа!
Простыми словами можно сказать, что ядра-потоки помогают друг другу в беде, если кого-то из них заваливают.
На самом деле в литературе эта технология так и называется "work stealing".

Классная статья на тему:
https://www.google.com/amp/s/nuancesprog.ru/p/11996/%3famp
🤔2
#functionalinterface

Допустим надо получить длину строки.
Пишем в коментах - какой вариант вам нравиться и почему?
1. s -> s.length()
2. String::length

Мне нравится, когда в коде используется method reference с двойным двоеточием :: лаконично и красиво. О рекомендации по method reference кстати пишет и Джошуа Блох в книге "Effective Java".

Есть такой вид интерфейсов - "функциональный интерфейс" – содержит только 1 абстрактный метод, и позволяют получить возможность делать method reference :: и пользоваться лямбда выражениями ->.

На такие интерфейсы обычно вешается аннотация @FunctionalInterface - обеспечивает наличие только одного абстрактного метода.
ВАЖНО - default и static методы не в счёт.

https://javarush.ru/groups/posts/592-java-functional-interfaces
👍2
#spring #enabletransactionmanagement #transaction

С версии 3.1 Spring ввел аннотацию @EnableTransactionManagement, которая используется с аннотацией @Configuration над конфигурационными классами и включает поддержку бесшовной транзакций через аннотацию @Transactional.

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

ВАЖНО: если в методе с аннотацией @Transactional будут действия с БД в виде цикла и будет ошибка хотя бы в одном - то ни один элемент из списка не запишется.

Пример записи в виде цикла:
@Transactional
public void book(String... persons) {
for (String person : persons) {
log.info("Booking " + person + " in a seat...");
jdbcTemplate.update("insert into BOOKINGS(FIRST_NAME) values (?)", person);
}
};

https://spring-projects.ru/guides/managing-transactions/
👍3
#springscopes

Например, с помощью аннотаций
@Component
@Scope("prototype")
над классом, мы укажем, что бин создается каждый раз, когда бин необходим в качестве зависимости.

Ниже список областей видимостей, описанных в документации на момент написания:

singleton - По умолчанию. Создаётся единственный экземпляр. Для бинов без состояния(stateless).

prototype - создается каждый раз, когда бин необходим в качестве зависимости. Для бинов с сохранением состояния(stateful).

request - ограничен единственным HTTP запросом. (web компонент)

session - жизненный цикл экземпляра ограничен в пределах одной и той же HTTP сессии. (web-компонент)

global session - жизненный цикл экземпляра ограничен в пределах глобальной HTTP сессии. (web компонент)

application - жизненный цикл экземпляра ограничен в пределах ServletContext. (web компонент)

Пример:

@Component
@Scope("prototype")
public class GreetingServiceImpl implements GreetingService {
//вкусная начинка
}

https://spring-projects.ru/guides/lessons/lesson-2/
👍3
#springprofiles

Профиль в спринге - это именованная группа определений бинов.

Например, у вас есть два стенда, testing для тестов и production, где работает приложение. При этом у вас будут различаться параметры в окружениях.

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

@Configuration
public class AppConfig {

@Bean
@Profile("dev")
public DataSource devDataSource() {
// test options
}

@Bean
@Profile("production")
public DataSource productionDataSource() throws Exception {
// real options
}
}

Важно!
Если класс конфигурации аннатирован @Profile({"p1", "p2"}), то она будет действовать, если профили "р1" и/или "р2" будут активны. При @Profile({"p1", "!p2"}) конфигурация действует, если профиль "р1" активен или профиль "р2" не активен.

https://spring-projects.ru/guides/lessons/lesson-2/
#nonnull #npe

Чтобы сделать поле или параметр не null, добавь аннотацию @NonNull.
И не парься.
Ломбок сам сгенерит проверку на NullPointerException.

Разбор аннотации здесь:
https://projectlombok.org/features/NonNull
👍4
#мусор #unused

Если код в проекте не используется, то нечего его хранить. И поддерживать пакеты понятнее, если класс стоит на месте, то значит работает.
При необходимости через Git можно восстановить нужный класс из истории репозитория.
В IDEA есть инструменты инспекции и анализа кода.

Можно пойти таким путем:
Code > Analyze Code > Run Inspection by Name > Unused declaration.

https://intellij-support.jetbrains.com/hc/en-us/community/posts/360010821479-How-to-use-IntelliJ-IDEA-to-find-all-unused-code-
👍2
#todo

Пиши //TODO комментарии прям на месте "не отходя от кассы" пока помнишь что хотел сделать с классом или методом.
В IDEA есть отдельная вкладка снизу для отображения TODO и этим очень удобно пользоваться.

В отличии от записок из блокнотов, TODO не надо искать по проекту как иголку в стоге сена, он уже написан в том месте, где требуется лечение.
👍3🏆3
#forkjointask #completablefuture

Чтобы запустить ForkJoinTask в ForkJoinPool со своими настройками, мне удалось найти такое решение:

CompletableFuture<?> cf = CompletableFuture.runAsync(forJoinTask::invoke, customForkJoinPool);

В такой конструкции получаем классные плюсы:
1. Результаты объеденных CompletableFuture с отловом InterruptedException и ExecutionException исключений через CompletableFuture.allOf(cf1, cf2).get(), чего нет при вызовах через ForkJoinPool::invokeAll и ForkJoinTask::invokeAll.
2. Возможность управления поведением каждого из потоков с помощью богатого контракта CompletableFuture.
3. Использование настроек своего customForkJoinPool. Я как минимум делаю спец. имена ForkJoinWorkerThread потоков для каждого из сервисов в проекте.

Пример создания сustomForkJoinPool:

protected СustomForkJoinPool(int logicTasksCount) {
int availableProcessors = Runtime.getRuntime().availableProcessors();
ForkJoinPool.ForkJoinWorkerThreadFactory workerFactory = this::initWorkerFactory;
if (logicTasksCount < availableProcessors) {
this.threadPool = new ForkJoinPool(logicTasksCount, workerFactory, null, false);
} else {
this.threadPool = new ForkJoinPool(availableProcessors, workerFactory, null, false);
}
log.info("Thread pool parallelism level - {}.", threadPool.getParallelism());
}

private ForkJoinWorkerThread initWorkerFactory(ForkJoinPool pool) {
ForkJoinWorkerThread thread = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
thread.setName("MyService-" + thread.getPoolIndex());
return thread;
}

https://www.baeldung.com/java-completablefuture
https://www.baeldung.com/java-work-stealing
🤔1
#jokerconf

Скоро состоится одна из самых крупных площадок по Java разработке!
Вот список докладов по разделам:
https://jokerconf.com/talks/

Есть возможность попасть на кусочек пирога и бесплатно, подробнее здесь:
https://jokerconf.com/registration/personal/
#immutablemap

ImmutableMap на самом деле полезная вещь и порой недооценена там где она должна быть.
Уверен, что значения в мапе будут меняться? На самом деле?

Может достаточно сделать вот так:
ImmutableMap<String, String> immutableMap = ImmutableMap.<String, String>builder()
.putAll(someMutableMap)
.put("Costa Rica", "North America")
.build();

В таком виде получается безопасная мапа с которой не страшно работать при отсутствии необходимости модификации, особенно если ее надо отдать наружу из класса.

Подробнее здесь:
https://www.baeldung.com/java-immutable-maps
👍5
#singular

Удобно пользоваться аннотацией @Singular от Lombok в билдерах @Builder.
Аннотация автоматически генерирует возможность подавать элементы коллекции в билдере в виде:
.table(sourceTable)
.table(targetTable)

Вместо оборачивания всех подаваемых полей через конструкцию из древних веков - Arrays.asList(sourceTable, targetTable).

https://www.baeldung.com/lombok-builder-singular
🤓1
#lombokvar

Когда ты знаешь контекст и тебе быстро нужно определённое поле под рукой, то Lombok var - то что надо.
Достаточно написать вот так как на картинке (указано стрелкой) и стринги готовы к  работе.

ВАЖНО!
С этими var надо быть внимательным:
- при множестве таких полей не перепутать при работе
- не стоит давать малопонятные имена var полям
- это lazy тип, который получает себя от начинки.

https://www.baeldung.com/java-lombok-val-var
👌1
#cachedthreadpool

Важно контролировать кол-во потоков (thread) и задач (task) в работающем пуле (thread pool), в противном случае многопоточка может только навредить работе приложения.
Это связано с тем, что потоки и задачи в очереди кушают ресурсы (память и процессор).
Особенно это касается Cached Thread Pool.
В этом типе пула очередь не может хранить задачи и создаёт новый поток если все заняты.
Так же этот тип пула не рекомендуется для I/O задач ВВОДА-ВЫВОДА.
Он подходит для ограниченного кол-ва задач и маленьких по времени выполнения.

👉 Почитать здесь:
https://www.baeldung.com/java-executors-cached-fixed-threadpool

https://javarush.com/quests/lectures/jru.module2.lecture23
👍1
#agile

Работаю в аджайле с 2017 года.
И хочется здесь отметить пару моментов из реального опыта глазами разработчика.
Возможно пригодится.

В одном из проектов за нормально описанную архитектурную документацию сервиса меня уволили из-за того, что я хорошо её прорисовал, а надо было вместо этого делать быстро и ТЯП-ЛЯП, так как заказчик уже хочет по другому.
- "Главное вернеуровневую часть архитектуры нарисуй, чтобы что-то показать заказчику".
Тех. директор поддержал меня и хотел оставить, но ситуация ему не позволяла.

В текущем проекте я вижу как аджайл пытается быть натянутым на сложный проект backend происхождения и эта методология приводит к некачественной реализации.

Сформировалось мнение, что аджайл возможно будет полезен для сайта типа wildberries (frontend часть) потому, что:
1. Сайт уже кто-то нормально сделал и он работал ещё до мыслей об аджайле.
2. Пользователи (бизнес) могут конструктивно оценить фичи уже работающего сайта и их стоит учитывать в технической реализации.

Во всех остальных кейсах аджайл будет провоцировать на быстрый поиск ПОЛУ-СЫРОГО или пилотного функционала (возможно и с аутсорс сострудниками), его быструю адаптацию и доработку.

А настоящему Java разработчику важно:
- интересный стек с задачами
- участие с тем, чтобы то что написано проработало адекватное время и не было выброшено в связи со стихийными изменениями архитектуры
- хорошие ТЗ и ответственность сотрудников за свои области

Так что фокусируемся на качестве кода проекта и интересных темах!

Статья для почитать ниже
https://habr.com/ru/post/580326/
👍2
#transient

Когда класс участвует в сериализации, но есть поля, которые не нужны после десериализации, то вешай модификатор TRANSIENT на поле.
Это позволит:
- не упасть лицом в грязь, записав пароль пользователей в класс
- ускорить выполнение, освободив сериализацию от мусора.

Бывает так, что сериализация достаётся по наследству от родительского класса.
Как раз такой пример представлен на скриншоте. Но мне в данном случае не надо, чтобы мои поля участвовали в сериализации. Более того, если убрать TRANSIENT, то на класс ругается система проверки качества кода SonarQube.

https://javarush.com/groups/posts/2898-chto-skrihvaet-modifikator-transient-v-java
🤔1
#desing #interface

Вот 👉 эти два куска дерева на заборе недалеко от моего офиса - это тот случай, когда в дизайне проекта нехватило интерфесов для новой реализации!
По сути это легаси, которое нельзя удалить, из-за того, что на этом что-то работает 😭

То есть в какой-то момент нужна новая реализация на интерфейсе, а вместо этого в проекте абстрактный класс с уже прописанной в нём реализацией.

https://stackoverflow.com/questions/22847942/java-interface-reference
👌3👍1
#sparkdate #sparktimestamp

Работа с типами дата и таймстамп заслуживает отдельного внимания в Apache Spark.
Особенно если есть джоины или фильтрация наборов данных по такого рода колонкам.
В таком случае все значения надо СТРОГО приводить к одному формату!
Иначе плакали наши данные и кино 🎥 показывать не будут.

На скриншоте наглядно показан пример взятия первых 10 значений из полей при джоине у обоих сторон.

Например timestamp или string с типом date джоинить нельзя. Иногда спарк сам может справиться с конвертацией и выдрать дату из таймстампа, НО это риск, который может вылезти в самый неожиданный момент.

https://spark-school.ru/blogs/timestamp-functions/
👍4
#completablefuture

Хорошее видео с разбором overhead'а при асинхронном выполнении и результатами замеров.

Мне понравился момент, когда автор в начале говорит, что перед началом исследования сделал пост в соц. сети с вопросом о использовании CompletableFuture и главным отзывом было - "нихрена непонятно как пользоваться".

Так же на 13 минуте приводиться несколько вариантов завершения. Это и есть фото в этом посте.

От себя отмечу, что CompletableFuture цепочки это аналог Stream API в Java и нужно быть внимательным с методами. Какие-то из них блокирующие, а какие-то нет.

🎥 Видео:
https://youtu.be/W7iK74YA5NM

Примеры кода:
https://liakh-aliaksandr.medium.com/asynchronous-programming-in-java-with-completablefuture-47ab86458aab
🤔1
This media is not supported in your browser
VIEW IN TELEGRAM
#codereview

Видео 🎥 показывает что переживает разраб сделавший доработки и создавший Pull Request для код ревью! От души!

https://habr.com/ru/company/selectel/blog/660947/
😁1😢1