Осознал Kotlin спустя 7 лет
Когда я начинал изучать Kotlin, то первое, что было написано в книге, — что Kotlin – это выразительный и лаконичный язык.
Слушая эти заветы, я старательно пытался реализовать DSL. Код самого DSL получался коротким, но реализация этого DSL вызывала сомнения.
Пример:
И в SQL всё понятно: SQL – это декларативный язык, то есть мы описываем результат работы, а не саму работу.
Но когда дело доходило до того, что нужно мне (а это бизнес-процесс), я не знал, что делать.
Дело в том, что сама идея DSL сомнительная. Мне нужно сначала создать конструктор, а только потом писать проект. Я не хочу так. Я хочу сразу писать код, а ещё лучше – писать его меньше.
Как оказалось, всё упиралось в класс. Ответьте на вопрос: что является главным элементом языка Java? Объекты, методы? Нет, главный элемент – это класс. Всё живёт в нём. Парадигмы программирования – это не о классе, но в Java всё крутится вокруг класса, и из-за этого возникают проблемы многословности и многослойности.
Точно так же я и стал писать код на Kotlin: везде должен быть класс, даже если у него нет состояния. Причём такие примеры есть в самом языке Kotlin, например библиотека KoTest, DSL для тестирования.
Я сейчас дочитал только половину книги по микросервисам на Go, но мне сразу бросилось в глаза, что они не думают в рамках класса. Их там вовсе нет.
Я решил попробовать сделать так же.
У меня есть эталонное задание в курсе job4j ToDo-лист.
Для тех, кто не учился у меня, я опишу здесь архитектуру в рамках классов:
- StartUI – класс, который занимается графикой;
- Menu – класс, отвечает за управление меню;
- Action – классы, реализующие поведение меню;
- Store – хранилище для задач;
- Task – задачи.
И в Java-курсе, и в Kotlin-курсе я описывал эту задачу через классы.
И вроде бы всё логично.
StartUI зависит от Menu, Menu зависит от Action, Action от Task. Внедряй зависимости и полетел.
Если мы оценим код с позиции состояний, то поймём, что кроме Store и Task у нас нет реальных объектов.
StartUI, Menu, Action – это просто линейные операции без состояний.
То есть мне не надо писать лишний код, а только сфокусироваться на бизнес-процессе.
Ниже я опишу, как я его переделал.
Классы, которые действительно содержат состояния и от которых нельзя уйти:
А теперь то, что не классы и объекты, я описал функциями:
Обратите внимание, что эта функция не зависит от пользовательского кода или объектов. То есть весь код – это core. Я могу его протестировать, как угодно.
Второй момент, и я считаю его очень важным. Если это был бы класс, то я мог туда добавить ещё методы, а сейчас я ограничен только поведением моего меню. Никто не сможет запустить сюда грязные ручонки и дописать ещё методы. То есть за счёт языка я ограничил возможность раздувать код.
Когда я начинал изучать Kotlin, то первое, что было написано в книге, — что Kotlin – это выразительный и лаконичный язык.
Слушая эти заветы, я старательно пытался реализовать DSL. Код самого DSL получался коротким, но реализация этого DSL вызывала сомнения.
Пример:
fun <E> select(pool: BasicDataSource, sql: String,
ext: (ResultSet) -> E,
params: ArgStatement.() -> Unit): List<E> {
val rsl = ArrayList<E>()
pool.connection.use { cn ->
cn.prepareStatement(sql).use { st ->
val args = ArgStatement(st)
params(args)
val set = st.executeQuery()
while (set.next()) {
rsl.add(ext.invoke(set))
}
}
}
return rsl
}
// Использование
fun findByListId(levIds: Set<Int>): List<Level> =
select(pool, "SELECT * FROM level WHERE id = ANY(?)") {
arg(levIds)
}
И в SQL всё понятно: SQL – это декларативный язык, то есть мы описываем результат работы, а не саму работу.
Но когда дело доходило до того, что нужно мне (а это бизнес-процесс), я не знал, что делать.
Дело в том, что сама идея DSL сомнительная. Мне нужно сначала создать конструктор, а только потом писать проект. Я не хочу так. Я хочу сразу писать код, а ещё лучше – писать его меньше.
Как оказалось, всё упиралось в класс. Ответьте на вопрос: что является главным элементом языка Java? Объекты, методы? Нет, главный элемент – это класс. Всё живёт в нём. Парадигмы программирования – это не о классе, но в Java всё крутится вокруг класса, и из-за этого возникают проблемы многословности и многослойности.
Точно так же я и стал писать код на Kotlin: везде должен быть класс, даже если у него нет состояния. Причём такие примеры есть в самом языке Kotlin, например библиотека KoTest, DSL для тестирования.
Я сейчас дочитал только половину книги по микросервисам на Go, но мне сразу бросилось в глаза, что они не думают в рамках класса. Их там вовсе нет.
Я решил попробовать сделать так же.
У меня есть эталонное задание в курсе job4j ToDo-лист.
Для тех, кто не учился у меня, я опишу здесь архитектуру в рамках классов:
- StartUI – класс, который занимается графикой;
- Menu – класс, отвечает за управление меню;
- Action – классы, реализующие поведение меню;
- Store – хранилище для задач;
- Task – задачи.
И в Java-курсе, и в Kotlin-курсе я описывал эту задачу через классы.
И вроде бы всё логично.
StartUI зависит от Menu, Menu зависит от Action, Action от Task. Внедряй зависимости и полетел.
Если мы оценим код с позиции состояний, то поймём, что кроме Store и Task у нас нет реальных объектов.
StartUI, Menu, Action – это просто линейные операции без состояний.
То есть мне не надо писать лишний код, а только сфокусироваться на бизнес-процессе.
Ниже я опишу, как я его переделал.
Классы, которые действительно содержат состояния и от которых нельзя уйти:
data class Task(
val ID: Int,
val name: String
)
class Store {
private val mem = ArrayList<Task>()
fun add(task: Task) {
mem.add(task)
}
fun findById(ID: Int): Task? =
mem.find { it.ID == ID }
}
А теперь то, что не классы и объекты, я описал функциями:
fun startUI(input: (String) -> String, menu: Map<Int, () -> Boolean>) {
var selected = 0
do {
selected = input("Select: ").toInt()
val act = menu[selected] ?: continue
if (!act()) {
println("Error")
}
} while (selected != 0)
}Обратите внимание, что эта функция не зависит от пользовательского кода или объектов. То есть весь код – это core. Я могу его протестировать, как угодно.
Второй момент, и я считаю его очень важным. Если это был бы класс, то я мог туда добавить ещё методы, а сейчас я ограничен только поведением моего меню. Никто не сможет запустить сюда грязные ручонки и дописать ещё методы. То есть за счёт языка я ограничил возможность раздувать код.
🔥5
Опишем элементы меню:
Обратите внимание, что функция возвращает другую функцию, которая имеет крайне простой вызов.
В Java я передавал туда параметры
И теперь
Весь код уместился в один файл
Итог.
Свою версию курса по Kotlin считаю крайне неудачной, так как не увидел этого элемента языка сразу. Хотя считаю, что это упущение группы маркетинга языка. В новой версии курса я буду строить повествование только на идее отсутствия класса.
Также хотел бы подчеркнуть, что многие, как и я, сталкиваются с таким же непониманием языка, и вам крайне повезло, если вы пишете на Kotlin, а ваш тимлид понимает эту проблему.
P.S.
Код на Kotlin в таком стиле выглядит в 100500 раз читаемее, чем на Go, но скорость компиляции и исполняемые маленькие артефакты всё же заставят продолжать изучать Go дальше.
fun createTask(input: (String) -> String, store: Store): () -> Boolean = {
store.add(Task(
ID = 0,
name = input("Enter name: ")
))
true
}
fun findTask(input: (String) -> String, store: Store): () -> Boolean = {
val task = store.findById(
input("Enter ID: ").toInt()
)
if (task != null) {
println(task)
} else {
println("Not found")
}
task != null
}Обратите внимание, что функция возвращает другую функцию, которая имеет крайне простой вызов.
В Java я передавал туда параметры
execute(input, store)?, а сейчас я имею только вызов функции без зависимостей. И теперь
main: fun main() {
val store = Store()
val sc = Scanner(System.`in`)
val input: (String) -> String = {
print(it)
sc.nextLine()
}
val menu = mapOf(
1 to createTask(input, store),
2 to findTask(input, store)
)
startUI(input, menu)
}Весь код уместился в один файл
main.kt на 65 строк, где каждую функцию я могу протестировать. Итог.
Свою версию курса по Kotlin считаю крайне неудачной, так как не увидел этого элемента языка сразу. Хотя считаю, что это упущение группы маркетинга языка. В новой версии курса я буду строить повествование только на идее отсутствия класса.
Также хотел бы подчеркнуть, что многие, как и я, сталкиваются с таким же непониманием языка, и вам крайне повезло, если вы пишете на Kotlin, а ваш тимлид понимает эту проблему.
P.S.
Код на Kotlin в таком стиле выглядит в 100500 раз читаемее, чем на Go, но скорость компиляции и исполняемые маленькие артефакты всё же заставят продолжать изучать Go дальше.
🔥4👍3
Стили программирования
Вчера пытался переписать свой проект антиспам-бота в функциональном стиле. Проект изначально написан на Kotlin, но я использовал классы.
После предыдущего поста, в котором я показывал, что одними функциями можно переписать учебный проект, я решил, что стоит попробовать переписать что-то большее, чем учебный проект.
Есть много вариантов проектирования систем. Я в курсе показывал слоеную архитектуру (Onion). В основе её лежит база данных. Поэтому я стал переписывать код из нижнего слоя Repository.
Я люблю тесты, но TDD считаю извращением. Сначала я хочу видеть продукт, а потом этот продукт обвязать тестами, чтобы я мог его дальше дорабатывать. А не сначала тесты, а потом продукт.
Есть два пути: интеграционные тесты и модульные. Я сторонник модульных тестов. В целом мне нравится идея, что чем меньше действий ты делаешь, тем лучше. Для интеграционных тестов мне нужно тестовое окружение, а для модульных – нет.
Но чтобы писать модульные тесты, мне нужно абстрагироваться от реальной базы данных. С первого взгляда ничего сложного: передаём функцию, описывающую поведение.
Вроде несложно, но далее идёт сервис, а ещё далее контроллер. Я прикинул, сколько параметров будет у такого контроллера. На этом этапе я сразу остановился. Сначала я поискал, как подобную проблему решают в чисто функциональных языках. Оказалось, что от проблем зависимостей никуда не уйти. Они передают объект контекст или контейнер с функциями.
Что такое контейнер с функциями? Это и есть класс. То есть всё обратно упёрлось в класс. Кстати, по этой причине я и не видел проектов, написанных в чисто функциональном стиле. Чтобы писать в таком стиле, нужно написать кучу кода ради внедрения зависимостей, как функции.
Поэтому новые языки – Kotlin, Go – это языки в мультипарадигменном стиле. То есть в основу нужно брать не стиль программирования, а здравый смысл. А он нам говорит: писать меньше кода и писать тесты.
Эти два принципа должны лежать в основе хорошего кода.
Вчера пытался переписать свой проект антиспам-бота в функциональном стиле. Проект изначально написан на Kotlin, но я использовал классы.
После предыдущего поста, в котором я показывал, что одними функциями можно переписать учебный проект, я решил, что стоит попробовать переписать что-то большее, чем учебный проект.
Есть много вариантов проектирования систем. Я в курсе показывал слоеную архитектуру (Onion). В основе её лежит база данных. Поэтому я стал переписывать код из нижнего слоя Repository.
Я люблю тесты, но TDD считаю извращением. Сначала я хочу видеть продукт, а потом этот продукт обвязать тестами, чтобы я мог его дальше дорабатывать. А не сначала тесты, а потом продукт.
Есть два пути: интеграционные тесты и модульные. Я сторонник модульных тестов. В целом мне нравится идея, что чем меньше действий ты делаешь, тем лучше. Для интеграционных тестов мне нужно тестовое окружение, а для модульных – нет.
Но чтобы писать модульные тесты, мне нужно абстрагироваться от реальной базы данных. С первого взгляда ничего сложного: передаём функцию, описывающую поведение.
fun saveFilter(insert: (query: String, args: Map<String, Any>) -> Unit, filter: Filter) {
val query = "INSERT INTO dionea_filter (name) VALUES (:name)"
val args = mapOf<String, Any>("name" to filter.name)
insert(query, args)
}insert – это функция, принимающая запрос и параметры.fun insert(sql2o: Sql2o): (String, args: Map<String, Any>) -> Unit = { query, args ->
val cnn = sql2o.open()
sql2o.open().use { connection ->
val exec = connection.createQuery(query)
args.forEach { (t, u) -> exec.addParameter(t, u) }
exec.executeUpdate()
}
}Вроде несложно, но далее идёт сервис, а ещё далее контроллер. Я прикинул, сколько параметров будет у такого контроллера. На этом этапе я сразу остановился. Сначала я поискал, как подобную проблему решают в чисто функциональных языках. Оказалось, что от проблем зависимостей никуда не уйти. Они передают объект контекст или контейнер с функциями.
Что такое контейнер с функциями? Это и есть класс. То есть всё обратно упёрлось в класс. Кстати, по этой причине я и не видел проектов, написанных в чисто функциональном стиле. Чтобы писать в таком стиле, нужно написать кучу кода ради внедрения зависимостей, как функции.
Поэтому новые языки – Kotlin, Go – это языки в мультипарадигменном стиле. То есть в основу нужно брать не стиль программирования, а здравый смысл. А он нам говорит: писать меньше кода и писать тесты.
Эти два принципа должны лежать в основе хорошего кода.
👍8🔥5
Курс Apache Kafka
16 апреля 2025 года, я разговаривал с Михаилом — выпускником курса, который окончил обучение в 2022 году. После завершения курса он сразу нашел работу, а спустя три года решил сменить проект. Наши беседы всегда интересны, особенно когда речь заходит о том, как меняется процесс найма в IT.
Михаил поделился своими наблюдениями о собеседованиях в 2025 году по сравнению с 2022-м. Он отметил, что 80% вопросов на собеседовании касались Apache Kafka. Это неудивительно, ведь микросервисная архитектура принесла множество вызовов, которых не было в монолитных приложениях. Основной из них — это работа с распределенными транзакциями. В нашем курсе мы также затронем эту тему.
Описание курса https://job4j.ru/profile/courses/21
Пишите, те что хочешь начать проходить. Открою демо доступ.
Повествование решил сделать на Kotlin. Меньше кода писать. Так что сразу два зайца получается и Kafka + Kotlin, Gradle.
16 апреля 2025 года, я разговаривал с Михаилом — выпускником курса, который окончил обучение в 2022 году. После завершения курса он сразу нашел работу, а спустя три года решил сменить проект. Наши беседы всегда интересны, особенно когда речь заходит о том, как меняется процесс найма в IT.
Михаил поделился своими наблюдениями о собеседованиях в 2025 году по сравнению с 2022-м. Он отметил, что 80% вопросов на собеседовании касались Apache Kafka. Это неудивительно, ведь микросервисная архитектура принесла множество вызовов, которых не было в монолитных приложениях. Основной из них — это работа с распределенными транзакциями. В нашем курсе мы также затронем эту тему.
Описание курса https://job4j.ru/profile/courses/21
Пишите, те что хочешь начать проходить. Открою демо доступ.
Повествование решил сделать на Kotlin. Меньше кода писать. Так что сразу два зайца получается и Kafka + Kotlin, Gradle.
🔥11
Необходимые шаблоны: Retry, Circuit Breaker на базе Resilience4j
Я стараюсь максимально поддерживать актуальный материал в курсах, поэтому пришлось добавить в блок по микросервисам несколько уроков про шаблоны.
- Retry [#505446]
- Circuit Breaker [#505444]
- Resilience4j [#505447]
И еще один шаблон для асинхронного режима — outbox.
Курс: https://job4j.ru/profile/courses/14
Я настоятельно рекомендую ознакомиться с этими шаблонами, потому что их активно спрашивают на собеседованиях.
Вот пример задания на код-ревью.
Я стараюсь максимально поддерживать актуальный материал в курсах, поэтому пришлось добавить в блок по микросервисам несколько уроков про шаблоны.
- Retry [#505446]
- Circuit Breaker [#505444]
- Resilience4j [#505447]
И еще один шаблон для асинхронного режима — outbox.
Курс: https://job4j.ru/profile/courses/14
Я настоятельно рекомендую ознакомиться с этими шаблонами, потому что их активно спрашивают на собеседованиях.
Вот пример задания на код-ревью.
// Микросервис для обработки заказов, который взаимодействует с платежной системой и Kafka
@Service
public class OrderService {
private final PaymentClient paymentClient;
private final OrderRepository orderRepo;
private final KafkaTemplate<String, OrderEvent> kafkaTemplate;
@Transactional
public void processOrder(Order order) {
orderRepo.save(order);
paymentClient.charge(order.getUserId(), order.getAmount());
kafkaTemplate.send("order_events", new OrderEvent(order));
}
}
@FeignClient(name = "payment-service", url = "${payment.service.url}")
public interface PaymentClient {
@Retryable(maxAttempts = 5)
@PostMapping("/charge")
void charge(@RequestParam String userId,
@RequestParam BigDecimal amount);
}
@Service
@RequiredArgsConstructor
public class OrderEventConsumer {
private final NotificationService notificationService;
private final OrderRepository orderRepo;
@KafkaListener(topics = "order_events")
public void handleEvent(OrderEvent event) {
Order order = orderRepo.findById(event.getOrderId()).orElseThrow();
notificationService.sendEmail(order.getUserEmail(), "Order processed");
order.markAsCompleted();
orderRepo.save(order);
}
}
👍4🤩1
Бойко́т переводной литературе
Часто слышу, что ребята ругают переводную техническую литературу. Ранее я к этому относился спокойно и особо проблем не замечал. В целом не с чем было сравнить.
В моей личной библиотеке есть много книг, и переводных, и оригинальных. И я обратил внимание, что все оригинальные книги я прочитываю всегда до конца. Я имею в виду и на русском, и на английском. А переводные часто оказываются отложенными. Так и случилось с книгой по Apache Kafka. Я купил её, наверное, в 2019 году и бегло полистал.
А сейчас, когда я пишу курс по Apache Kafka, мне крайне нужна эта книга. Поэтому я её взял и стал читать от начала до конца.
Первое, на что я обратил внимание, — это то, что иногда я не могу уловить смысл предложений. Это странно. Я понимаю каждое слово, но не могу понять смысл предложения. Эта книга — перевод, поэтому я нашёл оригинал и сразу понял, что проблема в переводе.
Если провести аналогию в программировании, то любой перевод — это слой абстракции.
То есть, чтобы читать переведённую книгу, мне нужно выполнить три действия:
1. Понять русский текст.
2. Адаптировать его под английские термины.
3. Понять, что хотел донести автор оригинальной статьи.
Также я обратил внимание, что книгу в оригинале я прочитаю в разы быстрее, чем перевод. Это связано и с тем, что я описал выше, а также со способом восприятия иностранного языка. Если взять классическую схему обучения чтению, то освоение чтения начинают с элементарной части — буквы. Что в целом неверно, но это уже другая история.
Если мы учим второй язык, то элементарной частью для нас будет слово. Поэтому, когда я читаю иностранную литературу, то текст воспринимается словами или даже цепочками слов (chunk). Почему этого нет с переведённой статьёй? Потому что перевод — это интерпретация. А так как в 100% случаев переводчик — это не программист, то мы получаем дословный перевод, который мозг отказывается воспринимать.
Я часто вижу публикации на популярных технических платформах, где делают переводы иностранных статей. Может показаться, что они занимаются просветительской деятельностью, не все же владеют английским, чтобы читать в оригинале, но на самом деле это огромная медвежья услуга. Вас кормят, но не учат, как самому добыть еду.
То есть, это тоже одна из паразитных прослоек.
А как быть? Во-первых, если вы ещё не работаете в IT, то используйте любую литературу, которая вам поможет преодолеть барьер собеседования. А вот если вы уже на этой стороне, то я крайне советую начать учить английский.
Вы скажете: "Да, все так говорят, учи английский, а он не учится". Да, я тоже озадачился: а как тут помочь? Про это расскажу в следующей статье.
ПС. Я не фанатик английского языка, поэтому не техническую литературу с удовольствием читаю в переводе, так как там не требуется точности в терминах. Такой же подход и для авторских статей: например, автор выражает своё мнение об англоязычной статье и приводит какие-то куски переведённого текста — то тоже прочитаю с удовольствием.
Часто слышу, что ребята ругают переводную техническую литературу. Ранее я к этому относился спокойно и особо проблем не замечал. В целом не с чем было сравнить.
В моей личной библиотеке есть много книг, и переводных, и оригинальных. И я обратил внимание, что все оригинальные книги я прочитываю всегда до конца. Я имею в виду и на русском, и на английском. А переводные часто оказываются отложенными. Так и случилось с книгой по Apache Kafka. Я купил её, наверное, в 2019 году и бегло полистал.
А сейчас, когда я пишу курс по Apache Kafka, мне крайне нужна эта книга. Поэтому я её взял и стал читать от начала до конца.
Первое, на что я обратил внимание, — это то, что иногда я не могу уловить смысл предложений. Это странно. Я понимаю каждое слово, но не могу понять смысл предложения. Эта книга — перевод, поэтому я нашёл оригинал и сразу понял, что проблема в переводе.
Если провести аналогию в программировании, то любой перевод — это слой абстракции.
То есть, чтобы читать переведённую книгу, мне нужно выполнить три действия:
1. Понять русский текст.
2. Адаптировать его под английские термины.
3. Понять, что хотел донести автор оригинальной статьи.
Также я обратил внимание, что книгу в оригинале я прочитаю в разы быстрее, чем перевод. Это связано и с тем, что я описал выше, а также со способом восприятия иностранного языка. Если взять классическую схему обучения чтению, то освоение чтения начинают с элементарной части — буквы. Что в целом неверно, но это уже другая история.
Если мы учим второй язык, то элементарной частью для нас будет слово. Поэтому, когда я читаю иностранную литературу, то текст воспринимается словами или даже цепочками слов (chunk). Почему этого нет с переведённой статьёй? Потому что перевод — это интерпретация. А так как в 100% случаев переводчик — это не программист, то мы получаем дословный перевод, который мозг отказывается воспринимать.
Я часто вижу публикации на популярных технических платформах, где делают переводы иностранных статей. Может показаться, что они занимаются просветительской деятельностью, не все же владеют английским, чтобы читать в оригинале, но на самом деле это огромная медвежья услуга. Вас кормят, но не учат, как самому добыть еду.
То есть, это тоже одна из паразитных прослоек.
А как быть? Во-первых, если вы ещё не работаете в IT, то используйте любую литературу, которая вам поможет преодолеть барьер собеседования. А вот если вы уже на этой стороне, то я крайне советую начать учить английский.
Вы скажете: "Да, все так говорят, учи английский, а он не учится". Да, я тоже озадачился: а как тут помочь? Про это расскажу в следующей статье.
ПС. Я не фанатик английского языка, поэтому не техническую литературу с удовольствием читаю в переводе, так как там не требуется точности в терминах. Такой же подход и для авторских статей: например, автор выражает своё мнение об англоязычной статье и приводит какие-то куски переведённого текста — то тоже прочитаю с удовольствием.
👍14
Жаркий марафон - алго собес
Так как на собеседованиях продолжают активно давать задачи на алгоритмы. Предлагаю сделать летний марафон.
Одна задачу в неделю. Публиковать задачу буду тут в понедельник.
Задачи буду брать только с собеседований. а не случайные задачи.
Это увеличить шанс, что она будет на собеседовании тоже.
Решения можете скидывать: ссылки, либо из платформы, либо с github.
Задание для этой недели: Подмассив с их максимальной суммой | Алгоритм Кадане
https://job4j.ru/profile/topics/206/task_code/566/new_task
Как решать? В описании есть раздел объяснение. Сначала в уме попробуйте найти решение. А потом сравните с предложенным в объяснении, а только после этого пишите. Я советую писать прямо на платформе, потому что так же будет и в реальном собеседовании.
Так как на собеседованиях продолжают активно давать задачи на алгоритмы. Предлагаю сделать летний марафон.
Одна задачу в неделю. Публиковать задачу буду тут в понедельник.
Задачи буду брать только с собеседований. а не случайные задачи.
Это увеличить шанс, что она будет на собеседовании тоже.
Решения можете скидывать: ссылки, либо из платформы, либо с github.
Задание для этой недели: Подмассив с их максимальной суммой | Алгоритм Кадане
https://job4j.ru/profile/topics/206/task_code/566/new_task
Как решать? В описании есть раздел объяснение. Сначала в уме попробуйте найти решение. А потом сравните с предложенным в объяснении, а только после этого пишите. Я советую писать прямо на платформе, потому что так же будет и в реальном собеседовании.
❤11🔥7
Песочница для Go
Сегодня решил сам решить задачу по поиску подмассива с максимальной суммой на платформе.
https://job4j.ru/profile/topics/206/task_code/566/new_task
Поправил несколько неудобных моментов.
1. Нельзя запустить main. Для отладки на платформе это критично.
2. Нужно использовать мышку, чтобы запускать код.
Поэтому добавил.
1. Если в коде есть main, то можно его запустить.
2. Запустить можно через кнопку "Запустить" или сочетанием клавиш Shift+Enter.
Так же переделал реализацию песочницы. Мы готовим курс по GoLang и там тоже нужна песочница. В JDK 17< настройки можно было указать через SecurityManager, в GoLang такого нет. Поэтому все переделал на Docker.
Если кто желает попробовать наш курс по GoLang, то пишите мне @parsentev.
Будете фокус группой. Единственное условие у вас должен быть опыт работы хотя бы год, Обучение бесплатное.
https://job4j.ru/profile/topics/206/task_code/566/new_task
Сегодня решил сам решить задачу по поиску подмассива с максимальной суммой на платформе.
https://job4j.ru/profile/topics/206/task_code/566/new_task
Поправил несколько неудобных моментов.
1. Нельзя запустить main. Для отладки на платформе это критично.
2. Нужно использовать мышку, чтобы запускать код.
Поэтому добавил.
1. Если в коде есть main, то можно его запустить.
2. Запустить можно через кнопку "Запустить" или сочетанием клавиш Shift+Enter.
Так же переделал реализацию песочницы. Мы готовим курс по GoLang и там тоже нужна песочница. В JDK 17< настройки можно было указать через SecurityManager, в GoLang такого нет. Поэтому все переделал на Docker.
Если кто желает попробовать наш курс по GoLang, то пишите мне @parsentev.
Будете фокус группой. Единственное условие у вас должен быть опыт работы хотя бы год, Обучение бесплатное.
https://job4j.ru/profile/topics/206/task_code/566/new_task
👍5❤1
Завершил Курс по DevOps
Добавил важные уроки.
Сбор логов | Loki [#505404]
AlertManager | Loki | ERROR [#505405]
AlertManager | Prometheus | Health check [#505406]
Далее я соберу отзывы, пожелания и потом доработаю материал.
Например, я рассматриваю Jenkins, а ребята говорят, что лучше GitLab развернуть. В новой версии тогда на нем сделаю.
Не стал добавлять темы с GitOps, ArgoCD, Flux, потому что очень много вышло.
В целом эти решения тяжеловесные, даже не смотря на то, что я разворачивал минимальные приложения.
Так же вместо ELK, я просто взял Loki и сделал все через Prometheus + Grafana вышло в разы проще.
Описание курса тут https://job4j.ru/profile/courses/35
Немного своих впечатлений о процессе создания этого курса "Работает - не лезь". В программировании я вижу код и могу даже залезть внутрь приложения. А в DevOps я ограничен логами. Поэтому порой приходилось сидеть по нескольку часов, чтобы осознать, где я что-то прописал не так. Еще один важный момент - это совместимости версий в K8s. Все сервисы разворачиваются в кластере K8s через Helm. Часто было так, что приложение не стартовало, потому что ему не хватало настроек в этом Helm. Лезешь в лог, разбираешься для чего это нужно, потом обновляешь. Поэтому фраза "работает не лезь" - этот как раз про DevOps )).
Добавил важные уроки.
Сбор логов | Loki [#505404]
AlertManager | Loki | ERROR [#505405]
AlertManager | Prometheus | Health check [#505406]
Далее я соберу отзывы, пожелания и потом доработаю материал.
Например, я рассматриваю Jenkins, а ребята говорят, что лучше GitLab развернуть. В новой версии тогда на нем сделаю.
Не стал добавлять темы с GitOps, ArgoCD, Flux, потому что очень много вышло.
В целом эти решения тяжеловесные, даже не смотря на то, что я разворачивал минимальные приложения.
Так же вместо ELK, я просто взял Loki и сделал все через Prometheus + Grafana вышло в разы проще.
Описание курса тут https://job4j.ru/profile/courses/35
Немного своих впечатлений о процессе создания этого курса "Работает - не лезь". В программировании я вижу код и могу даже залезть внутрь приложения. А в DevOps я ограничен логами. Поэтому порой приходилось сидеть по нескольку часов, чтобы осознать, где я что-то прописал не так. Еще один важный момент - это совместимости версий в K8s. Все сервисы разворачиваются в кластере K8s через Helm. Часто было так, что приложение не стартовало, потому что ему не хватало настроек в этом Helm. Лезешь в лог, разбираешься для чего это нужно, потом обновляешь. Поэтому фраза "работает не лезь" - этот как раз про DevOps )).
👍17💯6
Go, как второй язык
А вы знали, что в GoLang всего 25 ключевых слов? Это в два раза меньше, чем в Java. Предположим, что и учить там в два раза меньше. Однако одна из первых фраз в книге Go 100:
Go is simple, but not easy. Это важно понимать, если вы только на пути в IT. На собеседовании по GoLang можно встретить классическую задачу на указатели.
Что выведет код и почему? В целом, я считаю, что задачи на то, что выведет код и почему, неуместны, так как у нас есть компилятор и тесты, чтобы не гадать, что он выведет. Конечно, это не касается многопоточных вещей.
В GoLang есть настоящие указатели, как в C++. Они не такие, как в Java, то есть это реальный указатель на участок памяти. Чтобы создать указатель, нужно начать переменную с символа амперсанда (&). А чтобы записать в переменную указателя, нужно использовать звездочку (*).
Код выше выведет
Или, как в Java, обратиться к полю:
Но это не интересно, а можно сказать, что возьми адрес указателя и запишу туда новый объект:
Это не значит, что язык плохой, что позволяет такое делать, а то, что он так же будет требовать много времени на изучение, как и любой другой язык. Однако все эти нюансы — это только особенности языка, которые по сравнению с элементами предметной области крайне небольшие.
Изначально я думал, что с Go решают какие-то крутые задачи по оптимизации, но на самом деле оказалось, что решают такие же задачи, как и в Java. То есть стек технологий и решений один в один как в Java: Docker, K8s, Redis и даже Kafka. Там же шаблоны отказоустойчивости, Retry, Circuit Breaker, Timeout, Outbox. Есть и другие проекты, например, по pentest и blockchain, но их крайне мало, около 40 вакансий.
С другой стороны, если посмотреть на курсы по Go, то можно увидеть корреляцию с Java: Go занимает меньше времени. Поэтому мы и решили проверить эту гипотезу с Михаилом.
Можно ли за 3-4 месяца перейти с Java на Go, при условии наличия коммерческого опыта и без потери в зарплате?
Для примера, в Go есть только слайсы и словари. Все другие структуры вам нужно реализовать самому, то есть нет необходимости учить Java Collection API.
Если у вас есть желание принять участие в нашем эксперименте по Go, пишите мне @parsentev.
А вы знали, что в GoLang всего 25 ключевых слов? Это в два раза меньше, чем в Java. Предположим, что и учить там в два раза меньше. Однако одна из первых фраз в книге Go 100:
Go is simple, but not easy. Это важно понимать, если вы только на пути в IT. На собеседовании по GoLang можно встретить классическую задачу на указатели.
Что выведет код и почему? В целом, я считаю, что задачи на то, что выведет код и почему, неуместны, так как у нас есть компилятор и тесты, чтобы не гадать, что он выведет. Конечно, это не касается многопоточных вещей.
type Person struct {
Name string
}
func changeName(p *Person) {
p = &Person{
Name: "Alice",
}
}
func main() {
person := &Person{
Name: "Bob",
}
fmt.Println(person.Name)
changeName(person)
fmt.Println(person.Name)
}В GoLang есть настоящие указатели, как в C++. Они не такие, как в Java, то есть это реальный указатель на участок памяти. Чтобы создать указатель, нужно начать переменную с символа амперсанда (&). А чтобы записать в переменную указателя, нужно использовать звездочку (*).
Код выше выведет
Bob, Bob. Почему? Потому что функция changeName записывает новый указатель в локальную переменную. Вопрос: как поправить код, чтобы вывел Bob, Alice?Или, как в Java, обратиться к полю:
func changeName(p *Person) {
p.Name = "Alice"
}Но это не интересно, а можно сказать, что возьми адрес указателя и запишу туда новый объект:
func changeName(p *Person) {
*p = Person{
Name: "Alice",
}
}Это не значит, что язык плохой, что позволяет такое делать, а то, что он так же будет требовать много времени на изучение, как и любой другой язык. Однако все эти нюансы — это только особенности языка, которые по сравнению с элементами предметной области крайне небольшие.
Изначально я думал, что с Go решают какие-то крутые задачи по оптимизации, но на самом деле оказалось, что решают такие же задачи, как и в Java. То есть стек технологий и решений один в один как в Java: Docker, K8s, Redis и даже Kafka. Там же шаблоны отказоустойчивости, Retry, Circuit Breaker, Timeout, Outbox. Есть и другие проекты, например, по pentest и blockchain, но их крайне мало, около 40 вакансий.
С другой стороны, если посмотреть на курсы по Go, то можно увидеть корреляцию с Java: Go занимает меньше времени. Поэтому мы и решили проверить эту гипотезу с Михаилом.
Можно ли за 3-4 месяца перейти с Java на Go, при условии наличия коммерческого опыта и без потери в зарплате?
Для примера, в Go есть только слайсы и словари. Все другие структуры вам нужно реализовать самому, то есть нет необходимости учить Java Collection API.
Если у вас есть желание принять участие в нашем эксперименте по Go, пишите мне @parsentev.
👍8
Курс Apache Kafka | Задача с собеседования
Я переключился на курс по Apache Kafka.
Добавил новый урок.
Архитектура Kafka [#505452]
В нем рассмотрел настройку разделов в теме.
Часто на собеседовании можно услышать вопрос, о том, что будет если у нас один раздел в теме и два потребителя?
Пишите ответы в комментариях .
👉 Описание курса https://job4j.ru/profile/courses/21
Я переключился на курс по Apache Kafka.
Добавил новый урок.
Архитектура Kafka [#505452]
В нем рассмотрел настройку разделов в теме.
Часто на собеседовании можно услышать вопрос, о том, что будет если у нас один раздел в теме и два потребителя?
Пишите ответы в комментариях .
👉 Описание курса https://job4j.ru/profile/courses/21
🔥3
job4j.ru - Практика. Ревью. Результат. pinned «Кафка для линейного программиста За этот месяц уже несколько человек жаловались, что застряли на уровне мидл. На самом деле это распространённая ситуация. Как говорится, под лежачий камень вода не течёт. Расскажу эту ситуацию на примере английского языка.…»
Внутренний диалог и иностранный язык
Продолжу тему иностранного языка. Как вы знаете, я активно практикую йогу, потому что она помогает решать самые разные задачи в физическом и ментальном плане. В физическом плане всё понятно: асаны в йоге можно сравнить с любимыми спортивными упражнениями, но в спорте нет ментальных практик. Если упростить, йога — это концентрация на объекте наблюдения, например на дыхании, или, наоборот, на мыслительном процессе, но без погружения в него.
Попробуйте сами непрерывно понаблюдать за дыханием — через короткий промежуток времени вы поймаете себя на мысли, что уже не наблюдаете за дыханием, а думаете о других вещах.
На самом деле процесс переключения крайне важен, так как он позволяет найти опору в мыслительной деятельности. Наш ум всегда находится в потоке мыслей — это его природа. Как река не может стоять на месте, так и ум не может молчать, но мы можем им управлять.
Приведу пример: когда мы читаем про себя, у нас работает внутренний диалог, а когда мы читаем вслух, внутреннего диалога уже нет. Поэтому психологи часто рекомендуют общаться с друзьями, чтобы развеять плохие мысли: в процессе общения внутренний диалог переключается на внешний, что позволяет успокоить ум.
Тот же феномен работает и с иностранным языком: если мы читаем, мыслительный диалог идёт на этом языке. Поэтому, если есть возможность, читайте вслух.
Этот же приём используется при чтении программного кода.
Посмотрите на пример кода на Rust:
Я уверен на 100%, что вы смогли прочитать и понять этот код. Обратите внимание, что ваш мозг интерпретировал его по-своему, даже без знания синтаксиса Rust. Вам, конечно, не понятны все нюансы, но общий смысл вы уловили: описать структуру данных, дать ей функцию, создать объект этой структуры и вызвать функцию.
А теперь вернёмся к английскому языку. У меня появилась идея создать серию уроков, которая позволит читать английские книги и статьи в оригинале. Составить такой материал через ChatGPT несложно. Для чтения Reddit нужен словарный запас около 4000–6000 слов — это вполне реально, ведь многие IT-термины либо вовсе не переводятся (например, «commit»), либо имеют аналогичное звучание (например, «transaction»).
Однако встал вопрос: что делать с внутренним диалогом? Проблема в том, что мы будем неправильно произносить английские слова, но я пришёл к выводу, что это не так важно. Главное — отказаться от дословного перевода, как в примере с Rust-кодом, и сосредоточиться на понимании смысла предложения, а не на буквальном переводе.
Я знаю, что среди моей аудитории есть лингвисты. Если у кого-то есть желание принять участие в этом проекте, пишите мне @parsentev.
Продолжу тему иностранного языка. Как вы знаете, я активно практикую йогу, потому что она помогает решать самые разные задачи в физическом и ментальном плане. В физическом плане всё понятно: асаны в йоге можно сравнить с любимыми спортивными упражнениями, но в спорте нет ментальных практик. Если упростить, йога — это концентрация на объекте наблюдения, например на дыхании, или, наоборот, на мыслительном процессе, но без погружения в него.
Попробуйте сами непрерывно понаблюдать за дыханием — через короткий промежуток времени вы поймаете себя на мысли, что уже не наблюдаете за дыханием, а думаете о других вещах.
На самом деле процесс переключения крайне важен, так как он позволяет найти опору в мыслительной деятельности. Наш ум всегда находится в потоке мыслей — это его природа. Как река не может стоять на месте, так и ум не может молчать, но мы можем им управлять.
Приведу пример: когда мы читаем про себя, у нас работает внутренний диалог, а когда мы читаем вслух, внутреннего диалога уже нет. Поэтому психологи часто рекомендуют общаться с друзьями, чтобы развеять плохие мысли: в процессе общения внутренний диалог переключается на внешний, что позволяет успокоить ум.
Тот же феномен работает и с иностранным языком: если мы читаем, мыслительный диалог идёт на этом языке. Поэтому, если есть возможность, читайте вслух.
Этот же приём используется при чтении программного кода.
Посмотрите на пример кода на Rust:
struct SeaCreature {
noise: String,
}
impl SeaCreature {
fn get_sound(&self) -> &str {
&self.noise
}
}
fn main() {
let creature = SeaCreature {
noise: String::from("blub"),
};
println!("{}", creature.get_sound());
}Я уверен на 100%, что вы смогли прочитать и понять этот код. Обратите внимание, что ваш мозг интерпретировал его по-своему, даже без знания синтаксиса Rust. Вам, конечно, не понятны все нюансы, но общий смысл вы уловили: описать структуру данных, дать ей функцию, создать объект этой структуры и вызвать функцию.
А теперь вернёмся к английскому языку. У меня появилась идея создать серию уроков, которая позволит читать английские книги и статьи в оригинале. Составить такой материал через ChatGPT несложно. Для чтения Reddit нужен словарный запас около 4000–6000 слов — это вполне реально, ведь многие IT-термины либо вовсе не переводятся (например, «commit»), либо имеют аналогичное звучание (например, «transaction»).
Однако встал вопрос: что делать с внутренним диалогом? Проблема в том, что мы будем неправильно произносить английские слова, но я пришёл к выводу, что это не так важно. Главное — отказаться от дословного перевода, как в примере с Rust-кодом, и сосредоточиться на понимании смысла предложения, а не на буквальном переводе.
Я знаю, что среди моей аудитории есть лингвисты. Если у кого-то есть желание принять участие в этом проекте, пишите мне @parsentev.
🔥12
String в Java и Go
Как вы знаете, задача на работе и задача на собеседовании — это две совершенно разные вещи.
Напомню, что с Михаилом мы решили провести эксперимент с языком Go (GoLang). Эксперимент крайне простой: за 4–5 месяцев проработать материал по Go и вкатиться в Go-разработку без потери зарплаты.
Я сразу разделил это на два процесса: реальные задачи на работе и вопросы/задачи для собеседования.
В этой статье мы поговорим о вопросах, задаваемых на собеседовании.
Вас когда-нибудь спрашивали на собеседовании по Java о том, как устроен класс
Давайте разберёмся.
В Go строка (
Символы в кодировке UTF-8 могут занимать от 1 до 4 байтов. Поэтому в Go есть тип
Здесь
Если в строку попадают байты, не составляющие корректную UTF-8-последовательность, Go при разборе рун заменяет такой фрагмент на специальный символ
А как обстоят дела в Java?
В классическом варианте строки в Java представлены массивом 16-битных символов (UTF-16):
Начиная с Java 9 появился механизм оптимизации Compact Strings:
- Строки, содержащие только символы из Latin-1 (U+0000…U+00FF), хранятся по 1 байту на символ.
- Как только встречается хотя бы один символ за пределами Latin-1, используется UTF-16 (2 байта на кодовую единицу).
В Java тоже есть методы для работы с кодовыми точками:
Как вы знаете, задача на работе и задача на собеседовании — это две совершенно разные вещи.
Напомню, что с Михаилом мы решили провести эксперимент с языком Go (GoLang). Эксперимент крайне простой: за 4–5 месяцев проработать материал по Go и вкатиться в Go-разработку без потери зарплаты.
Я сразу разделил это на два процесса: реальные задачи на работе и вопросы/задачи для собеседования.
В этой статье мы поговорим о вопросах, задаваемых на собеседовании.
Вас когда-нибудь спрашивали на собеседовании по Java о том, как устроен класс
String? Думаю, нет, разве что о String Pool. А вот в Go это обязательный вопрос.Давайте разберёмся.
В Go строка (
string) — это неизменяемая (immutable) последовательность байтов, обычно кодирующих UTF-8. Под капотом строка представлена простым «хэдером» из двух машинных слов:// в пакете reflect есть аналогичная структура:
type StringHeader struct {
Data uintptr // указатель на первый байт в памяти
Len int // длина в байтах
}
Символы в кодировке UTF-8 могут занимать от 1 до 4 байтов. Поэтому в Go есть тип
rune: он позволяет прочитать нужное количество байтов, чтобы получить соответствующий символ из таблицы Unicode:name := "Hello, 世界"
for i, r := range name {
fmt.Println(i, string(r), r)
}
Здесь
i указывает на начало руны.Если в строку попадают байты, не составляющие корректную UTF-8-последовательность, Go при разборе рун заменяет такой фрагмент на специальный символ
� (U+FFFD), а длина такого «руна-элемента» считается равной 1 байту:b := []byte{0xff, 0xfe, 0x41} // 0x41 == 'A'
s := string(b)
fmt.Printf("len(bytes) = %d, len(runes) = %d\n",
len(b),
utf8.RuneCountInString(s),
)
// При range по строке
for i, r := range s {
fmt.Printf("idx %d: rune %U '%c'\n", i, r, r)
}А как обстоят дела в Java?
В классическом варианте строки в Java представлены массивом 16-битных символов (UTF-16):
public final class String {
private final char[] value;
private int hash;
// ...
}Начиная с Java 9 появился механизм оптимизации Compact Strings:
public final class String {
private final byte[] value;
private final byte coder; // 0 — LATIN1, 1 — UTF16
private int hash;
// ...
}- Строки, содержащие только символы из Latin-1 (U+0000…U+00FF), хранятся по 1 байту на символ.
- Как только встречается хотя бы один символ за пределами Latin-1, используется UTF-16 (2 байта на кодовую единицу).
В Java тоже есть методы для работы с кодовыми точками:
String.codePointAt() и String.codePoints().❤1
Алго-марафон | 2 неделя
Вначале хотел бы внести коррективы в план.
Изначальная идея заключалась в том, чтобы решать одну задачу в неделю. Но это крайне мало: такой темп годится разве что для того, чтобы не забыть совсем пройденный материал. Для нашего с Михаилом эксперимента такая скорость не подходит, поэтому пришлось внести изменения.
Примерно нужно решить 150 задач за 4–5 месяцев:
- Около 40 задач уровня easy.
- Около 100 задач уровня medium.
- И 10 задач уровня hard.
Выуживать задачи из YouTube оказалось неблагородным делом, ведь в 99 % это те же задачи с LeetCode. Поэтому я буду просто брать задачи оттуда.
Для задач easy и medium используем стандартный набор структур данных и алгоритмов:
- Два указателя
- Скользящее окно
- Бинарный поиск
- Хэш-таблица
- Стек
- Очередь
- Рекурсия
- Итерация
- Сортировка
- Префиксные суммы
- Жадные алгоритмы
- Битовые операции
- Динамическое программирование (простые задачи)
- BFS
- DFS
Всё это есть у нас в курсах: https://job4j.ru/profile/courses/5, https://job4j.ru/profile/courses/32 с теорией, задачами и проверкой менторами.
Поэтому на этой неделе нужно решить 10 задач уровня easy. Я приведу здесь ссылки на LeetCode, а завтра — аналоги на нашей платформе:
- https://leetcode.com/problems/two-sum/
- https://leetcode.com/problems/reverse-linked-list/
- https://leetcode.com/problems/valid-parentheses/
- https://leetcode.com/problems/merge-two-sorted-lists/
- https://leetcode.com/problems/best-time-to-buy-and-sell-stock/
- https://leetcode.com/problems/maximum-subarray/
- https://leetcode.com/problems/valid-anagram/
- https://leetcode.com/problems/invert-binary-tree/
- https://leetcode.com/problems/move-zeroes/
- https://leetcode.com/problems/intersection-of-two-arrays/
Кстати, я решаю их на Go, потому что в нём есть только массивы и карты, то есть остальные структуры приходится реализовывать самостоятельно (например, LinkedHashMap или HashSet). Я также настоятельно рекомендую всем, кто участвует в нашем эксперименте с Go, прорешать эти задачи именно на Go.
Свои решения вы можете оставить в комментариях под этим постом.
Вначале хотел бы внести коррективы в план.
Изначальная идея заключалась в том, чтобы решать одну задачу в неделю. Но это крайне мало: такой темп годится разве что для того, чтобы не забыть совсем пройденный материал. Для нашего с Михаилом эксперимента такая скорость не подходит, поэтому пришлось внести изменения.
Примерно нужно решить 150 задач за 4–5 месяцев:
- Около 40 задач уровня easy.
- Около 100 задач уровня medium.
- И 10 задач уровня hard.
Выуживать задачи из YouTube оказалось неблагородным делом, ведь в 99 % это те же задачи с LeetCode. Поэтому я буду просто брать задачи оттуда.
Для задач easy и medium используем стандартный набор структур данных и алгоритмов:
- Два указателя
- Скользящее окно
- Бинарный поиск
- Хэш-таблица
- Стек
- Очередь
- Рекурсия
- Итерация
- Сортировка
- Префиксные суммы
- Жадные алгоритмы
- Битовые операции
- Динамическое программирование (простые задачи)
- BFS
- DFS
Всё это есть у нас в курсах: https://job4j.ru/profile/courses/5, https://job4j.ru/profile/courses/32 с теорией, задачами и проверкой менторами.
Поэтому на этой неделе нужно решить 10 задач уровня easy. Я приведу здесь ссылки на LeetCode, а завтра — аналоги на нашей платформе:
- https://leetcode.com/problems/two-sum/
- https://leetcode.com/problems/reverse-linked-list/
- https://leetcode.com/problems/valid-parentheses/
- https://leetcode.com/problems/merge-two-sorted-lists/
- https://leetcode.com/problems/best-time-to-buy-and-sell-stock/
- https://leetcode.com/problems/maximum-subarray/
- https://leetcode.com/problems/valid-anagram/
- https://leetcode.com/problems/invert-binary-tree/
- https://leetcode.com/problems/move-zeroes/
- https://leetcode.com/problems/intersection-of-two-arrays/
Кстати, я решаю их на Go, потому что в нём есть только массивы и карты, то есть остальные структуры приходится реализовывать самостоятельно (например, LinkedHashMap или HashSet). Я также настоятельно рекомендую всем, кто участвует в нашем эксперименте с Go, прорешать эти задачи именно на Go.
Свои решения вы можете оставить в комментариях под этим постом.
🔥8
В Go за 5 месяцев. Горизонтальное масштабирование карьеры
Недавно читал про эксперимент ребят из Польши. Они фанатеют языком Go и хотели создать настолько плотный обучающий материал, чтобы за 10 часов перейти на Go в коммерческом проекте:
https://threedots.tech/post/we-quit-our-jobs/
Мне хотелось бы повторить их эксперимент, но в реалистичные сроки.
Изначально я разделил обучение на два параллельных процесса. Первый — то, что мы делаем на работе: микросервисы, REST, gRPC, Kafka, Docker, Kubernetes, Redis. Второй — то, что нужно для собеседования. Это два отдельных навыка.
Разберём, что нужно для работы:
1. Базовый синтаксис, ООП, ФП, структуры данных.
Учебный проект: телеграм-бот ToDo List с использованием PostgreSQL. Это позволит покрыть все основные темы языка, кроме корутин.
2. Корутины.
Учебный проект — классический граббер сайтов, например поиск вакансий на hh.ru.
3. Микросервисы.
Один сервис (gRPC + REST) общается со вторым через Kafka. JWT + Redis для авторизации и хранения сессий.
Разбор задач и вопросов на собеседовании (параллельный процесс, а не после первой части):
1. Алгоритмы и структуры данных: 40 easy, 100 medium, 10 hard.
2. Вопросы по корутинам и управлению памятью.
3. Системный дизайн.
Опыт работы?! Всё просто: в резюме указываем, что переписали какие-то микросервисы в своём проекте на Go — и они стали в разы быстрее. Поэтому хочется писать весь проект на Go, главное — самостоятельно переписать.
Эта схема подходит тем, кто уже работает с микросервисами.
Оцениваю такое обучение примерно в 5 месяцев ежедневных занятий, но никак не за 10 часов.
Зачем учить ещё один язык, решающий те же задачи, что и Java?
Во-первых, уровень абстракции: в Go вы ближе к системному программированию. Это особенно ценят на собеседованиях, например при вопросах о реализации строк или слайсов в Go.
Во-вторых, количество вакансий, на которые вы можете претендовать, сразу увеличивается вдвое. Стек остаётся одинаковым, меняется только базовый язык. Все концепции ООП, ФП, структуры данных, реляционные базы данных остаются такими же.
По сути это горизонтальное масштабирование вашей карьеры: резюме отличается только основным языком (Java или Go), а весь стек остаётся одинаковым.
Недавно читал про эксперимент ребят из Польши. Они фанатеют языком Go и хотели создать настолько плотный обучающий материал, чтобы за 10 часов перейти на Go в коммерческом проекте:
https://threedots.tech/post/we-quit-our-jobs/
Мне хотелось бы повторить их эксперимент, но в реалистичные сроки.
Изначально я разделил обучение на два параллельных процесса. Первый — то, что мы делаем на работе: микросервисы, REST, gRPC, Kafka, Docker, Kubernetes, Redis. Второй — то, что нужно для собеседования. Это два отдельных навыка.
Разберём, что нужно для работы:
1. Базовый синтаксис, ООП, ФП, структуры данных.
Учебный проект: телеграм-бот ToDo List с использованием PostgreSQL. Это позволит покрыть все основные темы языка, кроме корутин.
2. Корутины.
Учебный проект — классический граббер сайтов, например поиск вакансий на hh.ru.
3. Микросервисы.
Один сервис (gRPC + REST) общается со вторым через Kafka. JWT + Redis для авторизации и хранения сессий.
Разбор задач и вопросов на собеседовании (параллельный процесс, а не после первой части):
1. Алгоритмы и структуры данных: 40 easy, 100 medium, 10 hard.
2. Вопросы по корутинам и управлению памятью.
3. Системный дизайн.
Опыт работы?! Всё просто: в резюме указываем, что переписали какие-то микросервисы в своём проекте на Go — и они стали в разы быстрее. Поэтому хочется писать весь проект на Go, главное — самостоятельно переписать.
Эта схема подходит тем, кто уже работает с микросервисами.
Оцениваю такое обучение примерно в 5 месяцев ежедневных занятий, но никак не за 10 часов.
Зачем учить ещё один язык, решающий те же задачи, что и Java?
Во-первых, уровень абстракции: в Go вы ближе к системному программированию. Это особенно ценят на собеседованиях, например при вопросах о реализации строк или слайсов в Go.
Во-вторых, количество вакансий, на которые вы можете претендовать, сразу увеличивается вдвое. Стек остаётся одинаковым, меняется только базовый язык. Все концепции ООП, ФП, структуры данных, реляционные базы данных остаются такими же.
По сути это горизонтальное масштабирование вашей карьеры: резюме отличается только основным языком (Java или Go), а весь стек остаётся одинаковым.
👍14🔥1
Опять Кадане
Выше я привел список из 10 задача. Все задачи мне попадались раньше, кроме https://leetcode.com/problems/best-time-to-buy-and-sell-stock/
Сначала я оценил, как бы ее сделал сам и кроме прямого перебора больше решение не придумал. Пошел смотреть предлагаемые решения и как оказалось, то опять тут алгоритм Кадане. Сходу его применить тут не смог.
Для тренировки сделал еще и задачи на поиск максимального подмассива.
Пока в голову этот алгоритм не залез. Для этого случая, мы ищем локальным минимум. Если мы нашли новый, минимум, то идем считать уже от него. Время получается линейное.
в случае с подмассивом, все тоже самое, только мы оцениваем сумму, а не одно число.
В целом пост о том, что я тоже делаю эти задачи, чтобы поддержать тех кто тоже решить в нем принять участие.
Выше я привел список из 10 задача. Все задачи мне попадались раньше, кроме https://leetcode.com/problems/best-time-to-buy-and-sell-stock/
Сначала я оценил, как бы ее сделал сам и кроме прямого перебора больше решение не придумал. Пошел смотреть предлагаемые решения и как оказалось, то опять тут алгоритм Кадане. Сходу его применить тут не смог.
Для тренировки сделал еще и задачи на поиск максимального подмассива.
Пока в голову этот алгоритм не залез. Для этого случая, мы ищем локальным минимум. Если мы нашли новый, минимум, то идем считать уже от него. Время получается линейное.
в случае с подмассивом, все тоже самое, только мы оцениваем сумму, а не одно число.
В целом пост о том, что я тоже делаю эти задачи, чтобы поддержать тех кто тоже решить в нем принять участие.
👍9✍3
@Transation | Hibernate
У нас в курс https://job4j.ru/profile/courses/12 есть тестовое задание, где мы используем напрямую Hibernate.
https://github.com/MikhailChrn/job4j_cars/blob/10d435a795963ee839be915242001170ef0fdb39/src/main/java/ru/job4j/cars/repository/CrudRepository.java
Есть сервисы, которые не атомарно записывают данные.
Я попросил ученика сделать их атомарными. Я знаю, что это не тривиально в этом задании, потому что подобная проблема есть в Go.
Решение ученика.
https://github.com/MikhailChrn/job4j_cars/blob/10d435a795963ee839be915242001170ef0fdb39/src/main/java/ru/job4j/cars/service/impl/RegularPostService.java#L130-L140
Вопрос, можно ли так делать? Если нет, то как сделать правильно?
Решение пишите в комментариях к этому посту.
У нас в курс https://job4j.ru/profile/courses/12 есть тестовое задание, где мы используем напрямую Hibernate.
https://github.com/MikhailChrn/job4j_cars/blob/10d435a795963ee839be915242001170ef0fdb39/src/main/java/ru/job4j/cars/repository/CrudRepository.java
Есть сервисы, которые не атомарно записывают данные.
Я попросил ученика сделать их атомарными. Я знаю, что это не тривиально в этом задании, потому что подобная проблема есть в Go.
Решение ученика.
https://github.com/MikhailChrn/job4j_cars/blob/10d435a795963ee839be915242001170ef0fdb39/src/main/java/ru/job4j/cars/service/impl/RegularPostService.java#L130-L140
Вопрос, можно ли так делать? Если нет, то как сделать правильно?
Решение пишите в комментариях к этому посту.
GitHub
job4j_cars/src/main/java/ru/job4j/cars/repository/CrudRepository.java at 10d435a795963ee839be915242001170ef0fdb39 · MikhailChrn/job4j_cars
Contribute to MikhailChrn/job4j_cars development by creating an account on GitHub.
Задачи на эту неделю
https://leetcode.com/problems/climbing-stairs/
Темы: динамическое программирование
https://leetcode.com/problems/rotate-array/
Темы: массив, циклические сдвиги, реверс
https://leetcode.com/problems/third-maximum-number/
Темы: массив, сортировка или трёхкомнатный учёт
https://leetcode.com/problems/plus-one/
Темы: массив, симуляция сложения
https://leetcode.com/problems/pascals-triangle/
Темы: массив, динамическое программирование
https://leetcode.com/problems/intersection-of-two-linked-lists/
Темы: односвязный список, два указателя
https://leetcode.com/problems/linked-list-cycle/
Темы: односвязный список, два указателя (черепаха и заяц)
https://leetcode.com/problems/symmetric-tree/
Темы: дерево, рекурсия или BFS
https://leetcode.com/problems/single-number/
Темы: массив, побитовое XOR
https://leetcode.com/problems/majority-element/
Темы: массив, голосование Бойера–Мура или хэш-таблица
Черканите, в комментариях, кто еще пробует со мной этот марафон.
https://leetcode.com/problems/climbing-stairs/
Темы: динамическое программирование
https://leetcode.com/problems/rotate-array/
Темы: массив, циклические сдвиги, реверс
https://leetcode.com/problems/third-maximum-number/
Темы: массив, сортировка или трёхкомнатный учёт
https://leetcode.com/problems/plus-one/
Темы: массив, симуляция сложения
https://leetcode.com/problems/pascals-triangle/
Темы: массив, динамическое программирование
https://leetcode.com/problems/intersection-of-two-linked-lists/
Темы: односвязный список, два указателя
https://leetcode.com/problems/linked-list-cycle/
Темы: односвязный список, два указателя (черепаха и заяц)
https://leetcode.com/problems/symmetric-tree/
Темы: дерево, рекурсия или BFS
https://leetcode.com/problems/single-number/
Темы: массив, побитовое XOR
https://leetcode.com/problems/majority-element/
Темы: массив, голосование Бойера–Мура или хэш-таблица
Черканите, в комментариях, кто еще пробует со мной этот марафон.
LeetCode
Climbing Stairs - LeetCode
Can you solve this real interview question? Climbing Stairs - You are climbing a staircase. It takes n steps to reach the top.
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
Example 1:
Input: n = 2…
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
Example 1:
Input: n = 2…
👍4