Интеграция Liquibase с другими инструментами
Maven / Gradle
Maven
Добавьте зависимость в pom.xml:
Конфигурация через pom.xml:
Запуск миграций:
Gradle
Добавьте в build.gradle:
Запуск:
Spring Boot (автоконфигурация)
Spring Boot автоматически настраивает Liquibase, если он обнаружен в classpath.
Настройки в application.yml:
Поведение:
Миграции запускаются при старте приложения.
Можно отключить через spring.liquibase.enabled=false.
Расширенные функции Liquibase
Динамические свойства (property)
Позволяют выносить повторяющиеся значения в переменные.
Пример (YAML):
В liquibase.properties:
Через командную строку:
Контексты (contexts) и фильтрация changeSet’ов
Контексты позволяют выбирать, какие changeSet’ы применять в определённых окружениях.
Пример (YAML):
Как передать контекст?
Через командную строку:
В Spring Boot:
#Java #middle #Liquibase
Maven / Gradle
Maven
Добавьте зависимость в pom.xml:
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.25.0</version>
</dependency>
Конфигурация через pom.xml:
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>4.25.0</version>
<configuration>
<changeLogFile>src/main/resources/db/changelog/db.changelog-master.yaml</changeLogFile>
<url>jdbc:postgresql://localhost:5432/mydb</url>
<username>user</username>
<password>pass</password>
</configuration>
</plugin>
Запуск миграций:
mvn liquibase:update
Gradle
Добавьте в build.gradle:
plugins {
id 'org.liquibase.gradle' version '2.2.0'
}
dependencies {
liquibaseRuntime 'org.liquibase:liquibase-core:4.25.0'
liquibaseRuntime 'org.postgresql:postgresql:42.6.0'
}
liquibase {
changeLogFile 'src/main/resources/db/changelog/db.changelog-master.yaml'
url 'jdbc:postgresql://localhost:5432/mydb'
username 'user'
password 'pass'
}
Запуск:
gradle liquibaseUpdate
Spring Boot (автоконфигурация)
Spring Boot автоматически настраивает Liquibase, если он обнаружен в classpath.
Настройки в application.yml:
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: user
password: pass
liquibase:
change-log: classpath:db/changelog/db.changelog-master.yaml
enabled: true
contexts: dev # Фильтрация по контексту
Поведение:
Миграции запускаются при старте приложения.
Можно отключить через spring.liquibase.enabled=false.
Расширенные функции Liquibase
Динамические свойства (property)
Позволяют выносить повторяющиеся значения в переменные.
Пример (YAML):
databaseChangeLog:
- property:
name: default.schema
value: public
- changeSet:
id: 1
author: dev
changes:
- createTable:
tableName: ${default.schema}.users
columns:
- column:
name: id
type: INT
В liquibase.properties:
default.schema=public
Через командную строку:
liquibase update -Ddefault.schema=public
Контексты (contexts) и фильтрация changeSet’ов
Контексты позволяют выбирать, какие changeSet’ы применять в определённых окружениях.
Пример (YAML):
- changeSet:
id: 2
author: dev
context: "dev,test" # Будет выполнен только в dev и test
changes:
- insert:
tableName: users
columns:
- column:
name: username
value: "test_user"
- changeSet:
id: 3
author: dev
context: "prod" # Только в production
changes:
- createIndex:
tableName: users
indexName: idx_user_email
columns:
- column:
name: email
Как передать контекст?
Через командную строку:
liquibase update --contexts="dev"
В Spring Boot:
spring:
liquibase:
contexts: dev
#Java #middle #Liquibase
Best Practices
Организация changelog-файлов
Рекомендуемая структура:
Главный файл (db.changelog-master.yaml):
Почему так?
Удобно управлять версиями.
Легко находить изменения.
Тестирование миграций
Стратегии:
Локальная проверка:
Интеграционные тесты (JUnit + Testcontainers):
Работа в команде (избежание конфликтов)
Правила:
Именование changeSet’ов:
Используйте id: <дата>-<номер> (например, id: 20240315-1).
Указывайте автора (author: github_username).
Порядок изменений:
Не зависеть от порядка выполнения (например, не предполагать, что таблица A уже существует при создании B).
Использование preConditions:
Регулярные обновления:
Перед началом работы выполняйте liquibase update, чтобы получить актуальную схему.
#Java #middle #Liquibase
Организация changelog-файлов
Рекомендуемая структура:
src/main/resources/db/changelog/
├── db.changelog-master.yaml # Главный файл
├── changes/
│ ├── 001-create-tables.yaml
│ ├── 002-add-indexes.yaml
│ └── 003-insert-data.yaml
└── rollback/
├── 001-rollback.yaml # Ручные откаты
Главный файл (db.changelog-master.yaml):
databaseChangeLog:
- includeAll:
path: db/changelog/changes/
relativeToChangelogFile: true
Почему так?
Удобно управлять версиями.
Легко находить изменения.
Тестирование миграций
Стратегии:
Локальная проверка:
liquibase validate # Проверка синтаксиса
liquibase update # Применение в test-DB
Интеграционные тесты (JUnit + Testcontainers):
@Testcontainers
@SpringBootTest
class LiquibaseMigrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15");
@Test
void testMigrations() {
// Spring Boot автоматически применит миграции
assertTrue(true); # Если не упало — значит, успешно
}
}
Работа в команде (избежание конфликтов)
Правила:
Именование changeSet’ов:
Используйте id: <дата>-<номер> (например, id: 20240315-1).
Указывайте автора (author: github_username).
Порядок изменений:
Не зависеть от порядка выполнения (например, не предполагать, что таблица A уже существует при создании B).
Использование preConditions:
- changeSet:
id: 20240315-1
author: dev
preConditions:
- tableExists:
tableName: users
changes:
- addColumn:
tableName: users
column:
name: phone
type: VARCHAR(20)
Регулярные обновления:
Перед началом работы выполняйте liquibase update, чтобы получить актуальную схему.
#Java #middle #Liquibase
Что выведет код?
#Tasks
import java.util.Optional;
public class Task060625 {
public static void main(String[] args) {
Optional<String> opt = Optional.ofNullable(null)
.or(() -> Optional.of("Java"))
.map(v -> ((String) v).toUpperCase());
System.out.println(opt.orElse("Default"));
}
}
#Tasks
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
(можете предложить что-то из того, что предлагали на прошлой и позапрошлых неделях и что проиграло в голосовании!)
Не стесняемся!✌️
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
(можете предложить что-то из того, что предлагали на прошлой и позапрошлых неделях и что проиграло в голосовании!)
Не стесняемся!
Please open Telegram to view this post
VIEW IN TELEGRAM
Очень странно… 83 просмотра и 42 голоса
https://t.me/Java_for_beginner_dev/2477
Это реально столько активных пользователя?😭
Ау где остальные?👋
https://t.me/Java_for_beginner_dev/2477
Это реально столько активных пользователя?
Ау где остальные?
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegram
Java for Beginner
Вы еще читаете этот канал? 🤨
Да! Каждый день, все интересно, стараюсь не пропускать 🙂 / Да, периодически встречается что-то интересное 🤷♀️ / Редко, но заглядываю 🤫 / Канал больше не интересен, практически не захожу 👎 / Я сам(а) не понимаю зачем нахожусь…
Да! Каждый день, все интересно, стараюсь не пропускать 🙂 / Да, периодически встречается что-то интересное 🤷♀️ / Редко, но заглядываю 🤫 / Канал больше не интересен, практически не захожу 👎 / Я сам(а) не понимаю зачем нахожусь…
Что такое лямбда-выражения в Java? 🤓
Ответ:
Лямбда-выражения в Java — это краткий способ записи анонимных функций, которые можно передавать как аргументы в методы или сохранять в переменные. Они появились в Java 8 и позволяют писать более компактный и читаемый код, особенно при работе с функциональными интерфейсами (интерфейсами с одним абстрактным методом, например, Runnable, Comparator, Predicate).
Синтаксис лямбда-выражения:
(параметры) -> { тело_лямбды }
Если параметр один, скобки () можно опустить.
Если тело состоит из одной строки, фигурные скобки {} и return можно не писать.
#собеседование
Ответ:
Синтаксис лямбда-выражения:
(параметры) -> { тело_лямбды }
Если параметр один, скобки () можно опустить.
Если тело состоит из одной строки, фигурные скобки {} и return можно не писать.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
С 31.05 по 06.06
Предыдущий пост(с 24.05 по 30.05)
Следующая неделя
Воскресный мотивационный пост:
«Ты не программируешь — ты притворяешься, что учишься»
Выбранная голосованием тема:
Архитектурный шаблон MVC в Java Spring: теория, правила, ошибки
Запись встреч:
Многопоточка во всей красе. Часть 1.
Обучающие статьи:
Типы changesets и стратегии развертывания в Liquibase
Откаты (Rollback) и теги в Liquibase
Интеграция Liquibase с другими инструментами
Глубокое изучение типа данных boolean в Java
Ссылочные типы данных в Java
Пост под которым нет поздравлений:
Сегодня каналу исполнился год!🥳
Авторская статья (которая кому-то не понравилась):
Пагинация, которую начинаешь ненавидеть😵
Полезные статьи и видео:
Создаём HTTP-сервер на Java NIO
Большой гайд. Пишем микросервисы на Java и Spring Boot, заворачиваем в Docker, запускаем на EKS, мониторим на Grafana
ИСТОРИЯ НЕЙРОСЕТЕЙ - ОТ ПЕРЦЕПТРОНА ДО CHATGPT
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
#memory
Предыдущий пост(с 24.05 по 30.05)
Следующая неделя
Воскресный мотивационный пост:
«Ты не программируешь — ты притворяешься, что учишься»
Выбранная голосованием тема:
Архитектурный шаблон MVC в Java Spring: теория, правила, ошибки
Запись встреч:
Многопоточка во всей красе. Часть 1.
Обучающие статьи:
Типы changesets и стратегии развертывания в Liquibase
Откаты (Rollback) и теги в Liquibase
Интеграция Liquibase с другими инструментами
Глубокое изучение типа данных boolean в Java
Ссылочные типы данных в Java
Пост под которым нет поздравлений:
Сегодня каналу исполнился год!
Авторская статья (которая кому-то не понравилась):
Пагинация, которую начинаешь ненавидеть
Полезные статьи и видео:
Создаём HTTP-сервер на Java NIO
Большой гайд. Пишем микросервисы на Java и Spring Boot, заворачиваем в Docker, запускаем на EKS, мониторим на Grafana
ИСТОРИЯ НЕЙРОСЕТЕЙ - ОТ ПЕРЦЕПТРОНА ДО CHATGPT
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
#memory
Please open Telegram to view this post
VIEW IN TELEGRAM
Настройка OAuth2 для Gmail
Для Gmail предпочтительно использовать OAuth2.
Пример конфигурации:
Примечание: Зарегистрируйте приложение в Google Cloud Console и используйте библиотеку google-auth-library-oauth2-http для получения accessToken.
Создание сервиса отправки почты
Создадим сервис EmailService для отправки писем.
Конфигурация асинхронности:
#Java #middle #on_request #JavaMailSender
Для Gmail предпочтительно использовать OAuth2.
Пример конфигурации:
@Configuration
public class MailConfig {
@Bean
public JavaMailSender javaMailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("smtp.gmail.com");
mailSender.setPort(587);
mailSender.setUsername("your.email@gmail.com");
Properties props = mailSender.getJavaMailProperties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.auth.mechanisms", "XOAUTH2");
// Настройка OAuth2 токена через Google API Client Library
// Подробности: https://developers.google.com/identity/protocols/oauth2
return mailSender;
}
}
Примечание: Зарегистрируйте приложение в Google Cloud Console и используйте библиотеку google-auth-library-oauth2-http для получения accessToken.
Создание сервиса отправки почты
Создадим сервис EmailService для отправки писем.
@Service
public class EmailService {
@Autowired
private JavaMailSender mailSender;
@Autowired
private TemplateEngine templateEngine;
private static final Logger logger = LoggerFactory.getLogger(EmailService.class);
public void sendSimpleEmail(String to, String subject, String text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setSubject(subject);
message.setText(text);
mailSender.send(message);
}
public void sendHtmlEmail(String to, String subject, String htmlBody) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(to);
helper.setSubject(MimeUtility.encodeText(subject, "UTF-8", null));
helper.setText(htmlBody, true);
mailSender.send(message);
}
public void sendEmailWithAttachment(String to, String subject, String text, File attachment) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(to);
helper.setSubject(MimeUtility.encodeText(subject, "UTF-8", null));
helper.setText(text);
FileSystemResource file = new FileSystemResource(attachment);
helper.addAttachment(attachment.getName(), file);
mailSender.send(message);
}
@Async
public CompletableFuture<Void> sendSimpleEmailAsync(String to, String subject, String text IMPORTANT: text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setSubject(MimeUtility.encodeText(subject, "UTF-8", null));
message.setText(text);
mailSender.send(message);
return CompletableFuture.completedFuture(null);
}
public void sendTemplatedEmail(String to, String subject, String username) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
Context context = new Context();
context.setVariable("username", username);
String htmlBody = templateEngine.process("email-template", context);
helper.setTo(to);
helper.setSubject(MimeUtility.encodeText(subject, "UTF-8", null));
helper.setText(htmlBody, true);
mailSender.send(message);
}
}
Конфигурация асинхронности:
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.initialize();
return executor;
}
}
#Java #middle #on_request #JavaMailSender
Примеры кода
Простой текст:
HTML-письмо:
Вложение:
Обработка ошибок и логирование
JavaMailSender может выбрасывать исключения, которые нужно обрабатывать.
Основные исключения:
Пример отлова:
Повторные попытки
Используйте @Retryable из Spring Retry:
Зависимость:
Мониторинг и метрики
Для продакшен-приложений полезно отслеживать метрики отправки писем с помощью Spring Actuator:
Зависимость:
Безопасность и защита данных
Никогда не храните пароли в открытом виде в git-репозиториях.
Рекомендации:
Используйте переменные окружения или секреты (например, Kubernetes Secrets).
Применяйте Spring Cloud Vault или HashiCorp Vault.
Используйте шифрование с Jasypt.
Настройте OAuth2 для Gmail.
Пример с переменными окружения:
#Java #middle #on_request #JavaMailSender
Простой текст:
SimpleMailMessage message = new SimpleMailMessage();
message.setTo("user@example.com");
message.setSubject("Тестовое письмо");
message.setText("Привет из Spring Boot!");
mailSender.send(message);
HTML-письмо:
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo("user@example.com");
helper.setSubject(MimeUtility.encodeText("HTML письмо", "UTF-8", null));
helper.setText("<h1>Привет!</h1><p>Это HTML письмо.</p>", true);
mailSender.send(message);
Вложение:
File file = new File("/path/to/file.pdf");
FileSystemResource resource = new FileSystemResource(file);
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo("user@example.com");
helper.setSubject(MimeUtility.encodeText("Письмо с вложением", "UTF-8", null));
helper.setText("Смотри вложение!");
helper.addAttachment("file.pdf", resource);
mailSender.send(message);
Обработка ошибок и логирование
JavaMailSender может выбрасывать исключения, которые нужно обрабатывать.
Основные исключения:
MailAuthenticationException
MailSendException
MessagingException
Пример отлова:
try {
mailSender.send(message);
} catch (MailException e) {
logger.error("Ошибка отправки письма", e);
throw e;
}
Повторные попытки
Используйте @Retryable из Spring Retry:
@Retryable(value = MailException.class, maxAttempts = 3)
public void sendSimpleEmail(String to, String subject, String text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setSubject(subject);
message.setText(text);
mailSender.send(message);
}
Зависимость:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
Мониторинг и метрики
Для продакшен-приложений полезно отслеживать метрики отправки писем с помощью Spring Actuator:
@Service
public class EmailService {
@Autowired
private JavaMailSender mailSender;
@Autowired
private MeterRegistry meterRegistry;
public void sendSimpleEmail(String to, String subject, String text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setSubject(subject);
message.setText(text);
try {
mailSender.send(message);
meterRegistry.counter("email.sent.success").increment();
} catch (MailException e) {
meterRegistry.counter("email.sent.failure").increment();
throw e;
}
}
}
Зависимость:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
Безопасность и защита данных
Никогда не храните пароли в открытом виде в git-репозиториях.
Рекомендации:
Используйте переменные окружения или секреты (например, Kubernetes Secrets).
Применяйте Spring Cloud Vault или HashiCorp Vault.
Используйте шифрование с Jasypt.
Настройте OAuth2 для Gmail.
Пример с переменными окружения:
spring.config.import=optional:configserver:http://config-server
spring.mail.password=${MAIL_PASSWORD}
#Java #middle #on_request #JavaMailSender
Тестирование отправки почты
Интеграционные тесты с Testcontainers:
Зависимость:
Unit-тестирование:
Интеграция с очередями
Для отложенной отправки используйте RabbitMQ(ну или другой брокер сообщений):
Зависимость:
Распространенные ошибки и подводные камни
Неверная конфигурация SMTP (порт, шифрование).
Проблемы с двухфакторной авторизацией (особенно Gmail).
Ограничения на массовую рассылку (например, Gmail: ~500 писем/день для бесплатных аккаунтов).
Проблемы с кодировкой (например, кириллица в теме письма).
Отсутствие MIME-типа у вложений.
Блокировка сервером (например, Mail.ru требует DKIM и SPF).
Решение для кодировки:
#Java #middle #on_request #JavaMailSender
Интеграционные тесты с Testcontainers:
@Testcontainers
@SpringBootTest
public class EmailServiceTest {
@Container
private static final GreenMailContainer greenMail = new GreenMailContainer();
@Autowired
private EmailService emailService;
@Test
void shouldSendEmail() {
emailService.sendSimpleEmail("test@example.com", "Test Subject", "Test Body");
assertEquals(1, greenMail.getReceivedMessages().length);
}
}
Зависимость:
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>greenmail</artifactId>
<version>2.2.0</version>
<scope>test</scope>
</dependency>
Unit-тестирование:
@MockBean
private JavaMailSender mailSender;
@Test
void shouldSendMail() {
SimpleMailMessage message = new SimpleMailMessage();
emailService.sendSimpleEmail("to", "subject", "body");
verify(mailSender, times(1)).send(any(SimpleMailMessage.class));
}
Интеграция с очередями
Для отложенной отправки используйте RabbitMQ(ну или другой брокер сообщений):
@Service
public class EmailService {
@Autowired
private JavaMailSender mailSender;
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendEmailToQueue(String to, String subject, String text) {
EmailMessage email = new EmailMessage(to, subject, text);
rabbitTemplate.convertAndSend("emailQueue", email);
}
@RabbitListener(queues = "emailQueue")
public void processEmail(EmailMessage email) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(email.getTo());
message.setSubject(email.getSubject());
message.setText(email.getText());
mailSender.send(message);
}
@Data
static class EmailMessage {
private String to;
private String subject;
private String text;
}
}
Зависимость:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
Распространенные ошибки и подводные камни
Неверная конфигурация SMTP (порт, шифрование).
Проблемы с двухфакторной авторизацией (особенно Gmail).
Ограничения на массовую рассылку (например, Gmail: ~500 писем/день для бесплатных аккаунтов).
Проблемы с кодировкой (например, кириллица в теме письма).
Отсутствие MIME-типа у вложений.
Блокировка сервером (например, Mail.ru требует DKIM и SPF).
Решение для кодировки:
helper.setSubject(MimeUtility.encodeText("Тема на кириллице", "UTF-8", null));
#Java #middle #on_request #JavaMailSender
Сегодня продолжаем изучение многопоточки
В связи с техническими нюансами, встречу по многопоточке пришлось отменить.
Но мы же не могли оставить Вас без продолжения?😏
Поэтому @rKiraLis39 записал (за что ему огромное спасибо) для Вас видео в котором мы узнали:
⏺ Что такое атомарные операции в потоках
⏺ Что такое волатильность и как ее использовать
⏺ Как взаимодействовать с Executor'ами и как их настраивать
⏺ И много еще интересного
Ссылка на Youtube
Ссылка на Рутьюб
Смотрите, ставьте лайки, подписывайтесь на каналы!
В связи с техническими нюансами, встречу по многопоточке пришлось отменить.
Но мы же не могли оставить Вас без продолжения?
Поэтому @rKiraLis39 записал (за что ему огромное спасибо) для Вас видео в котором мы узнали:
Ссылка на Youtube
Ссылка на Рутьюб
Смотрите, ставьте лайки, подписывайтесь на каналы!
Please open Telegram to view this post
VIEW IN TELEGRAM
«Обучение Java — марафон, а не прыжок с трамплина»
Так вышло, что мое знакомство с Java и программированием в целом, началось еще в 2021 году.
Тогда, окрыленный надеждами на новую, интересную работу, я потратил приличное количество времени на изучение Java Core. Но как часто бывает, реальность продиктовала свои условия, я не смог осилить обучение и бросил его.
Периодически возвращаясь я понял, что придется начинать сначала.
И когда я смог подогнать жизненные условия к тому, чтобы бросить все и посвятить себя только обучению, которое в итоге привело меня сюда, я понял важную вещь - обучение программированию (да наверно любой другой сложной концепции) — это долгая, часто тяжелая дорога, где не будет "легко", но "результат" стоит того.
Вот, что важно понимать если ты только принял решение вступить на этот путь:
🟥 Начнем с массового, современного увлечения курсами, буткемпами, менторством, тренингами и подобной требухой.
Пойми простую вещь - кто обещает «легко и быстро» — 100% врет. Так практически не бывает, за исключением единичных примеров. Но ссылаясь на эти примеры, некоторые строят целые онлайн-школы и бизнес (на твоих деньгах).
И я не говорю, что ты не получишь ничего полезного на этих занятиях. НО! Ты не сможешь, к примеру за 3 месяца, стать конкурентным специалистом в Java, если ты обычный среднестатистический человек.
Ну никак, сорян, кто бы что не говорил🤷♀️
🟥 Ощущение «я тупой» — обязательный этап каждого.
Перед окунанием в "программирование", знай, что к примеру Java, уже отпраздновала 30-летие в этом году. А это, возможно больше чем ты живешь на свете.
А это значит, что изучение её (по крайней мере, как ощущаю это я) - это погружение в бесконечную кроличью нору.🐇
На каждую понятую тобой концепцию или алгоритм, за его спиной вырастут еще с десяток и ты постоянно будешь ощущать себя неполноценным😂
Не переживай - это нормально. Все проходят через это🙂
🟥 Медленный прогресс — это не глупость.
Пойми и прими, то, что порой в Java встречаются темы, которые не взять "с наскока". Ну никак.
И если ты вдруг, ловишь себя на мысли, что на какую-то тему ты тратишь неприлично долгое время - это не значит, что ты "не тянешь".
Просто это тоже нормально. Мы все разные, с разным бекграундом.
Важно не «как быстро», а как долго ты не сливаешься. Ведь в итоге самые стойкие — выигрывают, даже если тупят на старте.🏝
🟥 Ты просто обязан пройти через говнокод.
Знай, никто не пишет "красиво" и "правильно" с первого раза. Даже "гении".
А ты и я тем более.
Поэтому, как я писал в предыдущей статье - если первые месяцы ты будешь писать грязно, неэффективно и тупо — это тоже нормально и правильно.
Запомни: в начале пути, идеальный код — не твоя цель. Цель — живой и работающий код, а все остальное приложится.🧑💻
🟥 Ну и главное - обучение не должно быть "в кайф".
Если тебе в процессе обучения неприятно, неудобно и сложно — значит, ты делаешь правильно. (Особенно это актуально для тех кто за "30"👋 )
Твой мозг вышел из зоны комфорта, он испытывает стресс и пытается повлиять на тебя, вернув в теплые объятия неведения.
Твоя задача - ежедневно, ежеминутно, бороться с ленью, преодолевать алгоритмические и идейные трудности, выстраивая новые нейронные связи.
Комфорт — не показатель правильности выбранной методики обучения. Часто наоборот.
И вот когда ты преодолеешь себя, увидишь как на твою почту придет первый оффер, тогда ты как и я, поймешь, что и не стоило ждать удобств в обучении. (Тем более, что оно всегда будет продолжаться)
Ведь те трудности которые ты преодолел - сформировали из тебя того кто смог пройти собеседование и получить заветную работу.🥳
Главное вера в себя и свои силы💪
😎
Понравилась статья - поделись с другом и, будет тебе моя благодарность 👏
#motivation
Так вышло, что мое знакомство с Java и программированием в целом, началось еще в 2021 году.
Тогда, окрыленный надеждами на новую, интересную работу, я потратил приличное количество времени на изучение Java Core. Но как часто бывает, реальность продиктовала свои условия, я не смог осилить обучение и бросил его.
Периодически возвращаясь я понял, что придется начинать сначала.
И когда я смог подогнать жизненные условия к тому, чтобы бросить все и посвятить себя только обучению, которое в итоге привело меня сюда, я понял важную вещь - обучение программированию (да наверно любой другой сложной концепции) — это долгая, часто тяжелая дорога, где не будет "легко", но "результат" стоит того.
Вот, что важно понимать если ты только принял решение вступить на этот путь:
Пойми простую вещь - кто обещает «легко и быстро» — 100% врет. Так практически не бывает, за исключением единичных примеров. Но ссылаясь на эти примеры, некоторые строят целые онлайн-школы и бизнес (на твоих деньгах).
И я не говорю, что ты не получишь ничего полезного на этих занятиях. НО! Ты не сможешь, к примеру за 3 месяца, стать конкурентным специалистом в Java, если ты обычный среднестатистический человек.
Ну никак, сорян, кто бы что не говорил
Перед окунанием в "программирование", знай, что к примеру Java, уже отпраздновала 30-летие в этом году. А это, возможно больше чем ты живешь на свете.
А это значит, что изучение её (по крайней мере, как ощущаю это я) - это погружение в бесконечную кроличью нору.
На каждую понятую тобой концепцию или алгоритм, за его спиной вырастут еще с десяток и ты постоянно будешь ощущать себя неполноценным
Не переживай - это нормально. Все проходят через это
Пойми и прими, то, что порой в Java встречаются темы, которые не взять "с наскока". Ну никак.
И если ты вдруг, ловишь себя на мысли, что на какую-то тему ты тратишь неприлично долгое время - это не значит, что ты "не тянешь".
Просто это тоже нормально. Мы все разные, с разным бекграундом.
Важно не «как быстро», а как долго ты не сливаешься. Ведь в итоге самые стойкие — выигрывают, даже если тупят на старте.
Знай, никто не пишет "красиво" и "правильно" с первого раза. Даже "гении".
А ты и я тем более.
Поэтому, как я писал в предыдущей статье - если первые месяцы ты будешь писать грязно, неэффективно и тупо — это тоже нормально и правильно.
Запомни: в начале пути, идеальный код — не твоя цель. Цель — живой и работающий код, а все остальное приложится.
Если тебе в процессе обучения неприятно, неудобно и сложно — значит, ты делаешь правильно. (Особенно это актуально для тех кто за "30"
Твой мозг вышел из зоны комфорта, он испытывает стресс и пытается повлиять на тебя, вернув в теплые объятия неведения.
Твоя задача - ежедневно, ежеминутно, бороться с ленью, преодолевать алгоритмические и идейные трудности, выстраивая новые нейронные связи.
Комфорт — не показатель правильности выбранной методики обучения. Часто наоборот.
И вот когда ты преодолеешь себя, увидишь как на твою почту придет первый оффер, тогда ты как и я, поймешь, что и не стоило ждать удобств в обучении. (Тем более, что оно всегда будет продолжаться)
Ведь те трудности которые ты преодолел - сформировали из тебя того кто смог пройти собеседование и получить заветную работу.
Главное вера в себя и свои силы
#motivation
Please open Telegram to view this post
VIEW IN TELEGRAM
Предлагаем темы для разбора и публикации! 📖
В комментариях к данному посту предлагайте вопросы, которые вы хотели бы увидеть максимально подробно разобранными в постах, а если будет интересно то и на видео.
Голосование будет проводиться всю неделю, а статья или видео - выходить по выходным.
Примерные правила:
🟢 темы, не выше уровня middle, чтоб был интерес общим.
🟢 один человек - одна тема.
🟢 Тема должна быть отдельным теоретически-практическим вопросом. Готовый проект - это не тема!
Жду Ваших предложений!👏
В комментариях к данному посту предлагайте вопросы, которые вы хотели бы увидеть максимально подробно разобранными в постах, а если будет интересно то и на видео.
Голосование будет проводиться всю неделю, а статья или видео - выходить по выходным.
Примерные правила:
Жду Ваших предложений!
Please open Telegram to view this post
VIEW IN TELEGRAM
Голосуем за предложенные темы!
Anonymous Poll
54%
Stream API
15%
@Slf4j, логирование, кастомизация логов
13%
IO, NIO: работа с файловой системой
17%
Maven: жизненный цикл, фазы