Всем привет!
Я довольно часто провожу собесы Java разработчиков. Хотел бы написать про свои "черные метки", сильно снижающие шанс получить предложение о работе.
Ясно, что оценка будет комплексная - по теории, практике, софт-скилам, соответствию знаний и запрашиваемого "золота", но перечисленные ниже вещи сильно влияют на результат.
Поехали.
1) нет понимания основ Java, которые я ожидаю даже от джуна. Пример: переменную нельзя инициализировать результатом метода, обязательно должна быть инициализация через конструктор, а уже потом вызов метода с присвоением.
Для сравнения - не относится к основам незнание, когда можно не инициализировать переменную, а когда нет. Это приходит с опытом.
Еще примеры: непонимание иммутабельности строк или разницы между == и equals. Подчеркну - именно незнание. Можно не заметить этот баг в коде, такое к сожалению бывает, лечится подсказками IDEA и опытом
2) непонимание или отсутствие опыта работы со Spring Core, он же Spring Ioc. Spring сейчас - это наше все. Говорим Java приложение, подразумеваем Spring) Можно его не использовать: знаю компанию, где это запрещено по причине того, что Spring под капотом сложный и многие его используют не разбираясь в деталях. Это допустимый, хотя и спорный подход. Но он не отменяет того, что основы Spring нужно знать.
3) незнание модульных тестов. На мой взгляд это базовая практика, в отличие от более сложных вещей типа TDD, DDD, паттернов и ее нужно изучать вместе с Java и Spring
4) отсутсвие навыков работы с чужим кодом. На собес я предлагаю задачку типа код-ревью. Хотя бы 25% заложенных туда багов надо найти) Отдельный момент - есть баги логические, есть неоптимальный код, есть плохой код-стайл. Первые выглядят как более важные, но как правило их находят при тестировании - модульном или функциональном. Естественно, избавившись от них раньше, мы уменьшим время тестирования, Shift Left, Lead Time и все такое) Но вторые и третьи тоже важны, потому что практически любой код не является одноразовым. Его будут править - исправлять баги, добавлять новые фичи, рефакторить. Возможно даже другие люди. И разбираться в неоптимальном коде, где много boiler plate, отсутствует code стайл - то еще удовольствие. И куча потраченного времени, желание выкинуть все нафиг и переписать с нуля, а это еще куча потраченного времени...
5) Возвращаясь к задачке с код-ревью на собесе. В ней есть работа с данными, содержащимися в локальных переменных. Данные не передаются в метод через параметры - создаются в методе или читаются из файла. Но есть соискатели, которые начинают беспокоится за сохранность этих данных при многоточном вызове метода. Предлагают использовать StringBuffer для манипуляция со строками, или отказаться от static метода и хранить все в полях. Незачет) Локальные объекты хранятся в куче вместе со всеми, но ссылка на них есть только у одного потока, беспокоится незачем. Вообще это основы Java, но вынес в отдельный пункт, т.к. прямо бесит)
6) Для Middle + обязательно знание принципов SOLID. Можно не знать все паттерны или скептически относится к их практическому применению. Тут можно обсудить, поспорить. Но SOLID - это как аксиомы в математике. Основа разработки. Для джуна тоже будет огромным плюсом.
7) односложные ответы без попыток рассуждения. Все знать нельзя, да и не нужно, но рассуждая ты показываешь, на что способен. Сюда же я бы отнес проблемы с логикой. Например: "я первый раз вижу конструкцию do .. while, значит код работать не будет". Чтобы утверждать, что код не работает, нужно хорошо знать Java. Подход - я этого не знаю, поэтому оно работать не будет - плохой))) Везде, не только в Java. Правильно: я этого не знаю, поэтому я бы использовал другую конструкцию.
8) ну и очевидное - уход от прямых ответов, разливание воды ведрами, явная ложь.
#java #interview #solid
Я довольно часто провожу собесы Java разработчиков. Хотел бы написать про свои "черные метки", сильно снижающие шанс получить предложение о работе.
Ясно, что оценка будет комплексная - по теории, практике, софт-скилам, соответствию знаний и запрашиваемого "золота", но перечисленные ниже вещи сильно влияют на результат.
Поехали.
1) нет понимания основ Java, которые я ожидаю даже от джуна. Пример: переменную нельзя инициализировать результатом метода, обязательно должна быть инициализация через конструктор, а уже потом вызов метода с присвоением.
Для сравнения - не относится к основам незнание, когда можно не инициализировать переменную, а когда нет. Это приходит с опытом.
Еще примеры: непонимание иммутабельности строк или разницы между == и equals. Подчеркну - именно незнание. Можно не заметить этот баг в коде, такое к сожалению бывает, лечится подсказками IDEA и опытом
2) непонимание или отсутствие опыта работы со Spring Core, он же Spring Ioc. Spring сейчас - это наше все. Говорим Java приложение, подразумеваем Spring) Можно его не использовать: знаю компанию, где это запрещено по причине того, что Spring под капотом сложный и многие его используют не разбираясь в деталях. Это допустимый, хотя и спорный подход. Но он не отменяет того, что основы Spring нужно знать.
3) незнание модульных тестов. На мой взгляд это базовая практика, в отличие от более сложных вещей типа TDD, DDD, паттернов и ее нужно изучать вместе с Java и Spring
4) отсутсвие навыков работы с чужим кодом. На собес я предлагаю задачку типа код-ревью. Хотя бы 25% заложенных туда багов надо найти) Отдельный момент - есть баги логические, есть неоптимальный код, есть плохой код-стайл. Первые выглядят как более важные, но как правило их находят при тестировании - модульном или функциональном. Естественно, избавившись от них раньше, мы уменьшим время тестирования, Shift Left, Lead Time и все такое) Но вторые и третьи тоже важны, потому что практически любой код не является одноразовым. Его будут править - исправлять баги, добавлять новые фичи, рефакторить. Возможно даже другие люди. И разбираться в неоптимальном коде, где много boiler plate, отсутствует code стайл - то еще удовольствие. И куча потраченного времени, желание выкинуть все нафиг и переписать с нуля, а это еще куча потраченного времени...
5) Возвращаясь к задачке с код-ревью на собесе. В ней есть работа с данными, содержащимися в локальных переменных. Данные не передаются в метод через параметры - создаются в методе или читаются из файла. Но есть соискатели, которые начинают беспокоится за сохранность этих данных при многоточном вызове метода. Предлагают использовать StringBuffer для манипуляция со строками, или отказаться от static метода и хранить все в полях. Незачет) Локальные объекты хранятся в куче вместе со всеми, но ссылка на них есть только у одного потока, беспокоится незачем. Вообще это основы Java, но вынес в отдельный пункт, т.к. прямо бесит)
6) Для Middle + обязательно знание принципов SOLID. Можно не знать все паттерны или скептически относится к их практическому применению. Тут можно обсудить, поспорить. Но SOLID - это как аксиомы в математике. Основа разработки. Для джуна тоже будет огромным плюсом.
7) односложные ответы без попыток рассуждения. Все знать нельзя, да и не нужно, но рассуждая ты показываешь, на что способен. Сюда же я бы отнес проблемы с логикой. Например: "я первый раз вижу конструкцию do .. while, значит код работать не будет". Чтобы утверждать, что код не работает, нужно хорошо знать Java. Подход - я этого не знаю, поэтому оно работать не будет - плохой))) Везде, не только в Java. Правильно: я этого не знаю, поэтому я бы использовал другую конструкцию.
8) ну и очевидное - уход от прямых ответов, разливание воды ведрами, явная ложь.
#java #interview #solid
👍7
Всем привет!
Сегодня рассмотрим циклические зависимости. Начнем с уровня классов и дойдем до слоев приложения.
1) классы. Технически Java компилятор умеет компилировать взаимозависимые классы за счет того, что является многопроходным - https://ru.wikipedia.org/wiki/Многопроходный_компилятор
Какие могут быть проблемы?
Главная - ухудшается читаемость кода. Да, я снова про нее) Вначале мы читаем метод класса А, затем переходим в зависимый класс Б, потом снова в А - в общем логику кода понять сложно. И это я привел достаточно простой пример.
Соответственно такой код сложнее рефакторить, в примере выше изменение public Java API класса А или Б приведет к изменению и второго класса.
Еще минус - невозможно использовать Dependency Injection через конструктор, а это наиболее естественный путь.
2) пакеты и модули. Проблема с вынесением общего кода. Если пакет\модуль содержит какую-то общую логику и при этом ни от чего не зависит - вынести и переиспользовать его в других проектах элементарно.
К тому же если за направлением зависимостей не следить - со временем общая логика начнет зависеть от прикладной и возникнет цикл. Об том, что это плохо говорит буква D из SOLID - абстракция не должна зависеть от деталей.
3) слои приложения. Число слоев может быть разным. В гексагональной архитектуре их по сути два - бизнес-логика и слой сервисов: веб-контроллеры, доступ к БД, вызовы внешних сервисов... https://lumpov.blogspot.com/2021/01/hexagonal-architecture.html В MVC - view, controller и model. Еще распространен такой вариант - presentation, services, model, storage. Но если образуется цикл, то вся система рушится как карточный домик. Слои имеют смысл, когда можно проследить направление запросов и зависимостей. А цель их применения: разделение бизнес-логики и инфраструктурного кода, что дает возможность достаточно легко сменить\добавить storage или внешнее API. Плюс слои по разному тестируются.
#arch #solid
Сегодня рассмотрим циклические зависимости. Начнем с уровня классов и дойдем до слоев приложения.
1) классы. Технически Java компилятор умеет компилировать взаимозависимые классы за счет того, что является многопроходным - https://ru.wikipedia.org/wiki/Многопроходный_компилятор
Какие могут быть проблемы?
Главная - ухудшается читаемость кода. Да, я снова про нее) Вначале мы читаем метод класса А, затем переходим в зависимый класс Б, потом снова в А - в общем логику кода понять сложно. И это я привел достаточно простой пример.
Соответственно такой код сложнее рефакторить, в примере выше изменение public Java API класса А или Б приведет к изменению и второго класса.
Еще минус - невозможно использовать Dependency Injection через конструктор, а это наиболее естественный путь.
2) пакеты и модули. Проблема с вынесением общего кода. Если пакет\модуль содержит какую-то общую логику и при этом ни от чего не зависит - вынести и переиспользовать его в других проектах элементарно.
К тому же если за направлением зависимостей не следить - со временем общая логика начнет зависеть от прикладной и возникнет цикл. Об том, что это плохо говорит буква D из SOLID - абстракция не должна зависеть от деталей.
3) слои приложения. Число слоев может быть разным. В гексагональной архитектуре их по сути два - бизнес-логика и слой сервисов: веб-контроллеры, доступ к БД, вызовы внешних сервисов... https://lumpov.blogspot.com/2021/01/hexagonal-architecture.html В MVC - view, controller и model. Еще распространен такой вариант - presentation, services, model, storage. Но если образуется цикл, то вся система рушится как карточный домик. Слои имеют смысл, когда можно проследить направление запросов и зависимостей. А цель их применения: разделение бизнес-логики и инфраструктурного кода, что дает возможность достаточно легко сменить\добавить storage или внешнее API. Плюс слои по разному тестируются.
#arch #solid
Wikipedia
Многопроходный компилятор
Многопроходный компилятор (англ. Multi-pass compiler) — тип компилятора, который обрабатывает исходный код или абстрактное синтаксическое дерево программы несколько раз (в отличие от однопроходного компилятора, который проходит программу только один раз).…
👍2
Всем привет!
Я уже писал про паттерны https://t.me/javaKotlinDevOps/52 и их важность. Но есть штука поважнее паттернов - базовые принципы разработки. Чтобы стало понятнее приведу пример - SOLID.
Почему принципы важнее паттернов? Паттерн - это решение частной задачи. Лично я знаю больше паттернов, чем применял на практике) А в разработке я давно. Принципы же применимы практически к любой задачи.
Тот же S из SOLID - Single Responsibility: дорабатываешь какой-то метода - применим, создаешь новый класс - тоже, делишь код по модулям - аналогично, проектируешь набор микросервисов...
Я не люблю повторять то, что уже хорошо описано в интернете, поэтому вот статья с неплохим описанием - https://skillbox.ru/media/code/eto-klassika-eto-znat-nado-dry-kiss-solid-yagni-i-drugie-poleznye-sokrashcheniya/
Оффтопик - не ожидал от skillbox, обычно все ссылки у меня на Хабр или baeldung.
Что бы я добавил к описанным в статье принципам:
1) null safety. Плюсы: не получишь NullPointerException, не нужен код с проверкой на null, не нужно думать - так, на уровень выше я уже на null проверяю, тут вроде не нужно.. но если в будущем этот метод будет вызываться откуда-то еще. Жаль в Java ее достичь сложно, есть куча библиотек с аннотациями @Null\@NotNull, действуют они по разному, на эту тему можно отдельную статью написать. Важно то, что простого решения в Java нет. Зато есть в Kotlin)
2) иммутабельность. Главный плюс - большая устойчивость к ошибкам. Приведу пример: объект - это ссылка на область в памяти. Где еще в сервисе используется объект - часто быстро определить сложно. Вывод - меняя что-то в переданном в метод объекте можно поломать программу в неожиданном месте. Также неожиданным плюсом может быть большая производительность. Самый очевидный пример - иммутабельность строк. Еще - если у вас есть List и нужно убрать из него лишнее - возможно (возможно, надо проводить тесты!) оптимальнее будет создать новый список с нужными объектами, т.к. каждая модификация существующего - это перемещения в heap. Главное чтобы памяти было много и использовался современный сборщик мусора. Еще плюс - если объект иммутабельный, то его можно спокойно использовать в многопоточной программе. Изменения состояния нет, синхронизация доступа не нужна. Ну и бонусом - иммутабельный объект можно использовать как ключ, в том же HashSet\HashMap. В Java для иммутабельности есть records и final, в Kotlin - data class.
3) понятные наименования - я про переменные, методы, классы. Часто вижу две ошибки. Первая - злоупотребление сокращениями. Вторая - ситуативные названия. Т.е. при реализации конкретной фичи название кажется очевидным для автора кода. Но вот приходит новый разработчик. Он знает только о сервисе в целом, никакую старую аналитику он читать не будет, сразу полезет в код - в итоге многие названия покажутся ему непонятными. Общий принцип - называйте так, чтобы назначение кода было понятно новому разработчику. А любые более менее сложные условия выносите в методы с говорящими названиями. За подробностями - снова порекомендую книгу "Чистый код" Мартина.
#arch #patterns #solid
Я уже писал про паттерны https://t.me/javaKotlinDevOps/52 и их важность. Но есть штука поважнее паттернов - базовые принципы разработки. Чтобы стало понятнее приведу пример - SOLID.
Почему принципы важнее паттернов? Паттерн - это решение частной задачи. Лично я знаю больше паттернов, чем применял на практике) А в разработке я давно. Принципы же применимы практически к любой задачи.
Тот же S из SOLID - Single Responsibility: дорабатываешь какой-то метода - применим, создаешь новый класс - тоже, делишь код по модулям - аналогично, проектируешь набор микросервисов...
Я не люблю повторять то, что уже хорошо описано в интернете, поэтому вот статья с неплохим описанием - https://skillbox.ru/media/code/eto-klassika-eto-znat-nado-dry-kiss-solid-yagni-i-drugie-poleznye-sokrashcheniya/
Оффтопик - не ожидал от skillbox, обычно все ссылки у меня на Хабр или baeldung.
Что бы я добавил к описанным в статье принципам:
1) null safety. Плюсы: не получишь NullPointerException, не нужен код с проверкой на null, не нужно думать - так, на уровень выше я уже на null проверяю, тут вроде не нужно.. но если в будущем этот метод будет вызываться откуда-то еще. Жаль в Java ее достичь сложно, есть куча библиотек с аннотациями @Null\@NotNull, действуют они по разному, на эту тему можно отдельную статью написать. Важно то, что простого решения в Java нет. Зато есть в Kotlin)
2) иммутабельность. Главный плюс - большая устойчивость к ошибкам. Приведу пример: объект - это ссылка на область в памяти. Где еще в сервисе используется объект - часто быстро определить сложно. Вывод - меняя что-то в переданном в метод объекте можно поломать программу в неожиданном месте. Также неожиданным плюсом может быть большая производительность. Самый очевидный пример - иммутабельность строк. Еще - если у вас есть List и нужно убрать из него лишнее - возможно (возможно, надо проводить тесты!) оптимальнее будет создать новый список с нужными объектами, т.к. каждая модификация существующего - это перемещения в heap. Главное чтобы памяти было много и использовался современный сборщик мусора. Еще плюс - если объект иммутабельный, то его можно спокойно использовать в многопоточной программе. Изменения состояния нет, синхронизация доступа не нужна. Ну и бонусом - иммутабельный объект можно использовать как ключ, в том же HashSet\HashMap. В Java для иммутабельности есть records и final, в Kotlin - data class.
3) понятные наименования - я про переменные, методы, классы. Часто вижу две ошибки. Первая - злоупотребление сокращениями. Вторая - ситуативные названия. Т.е. при реализации конкретной фичи название кажется очевидным для автора кода. Но вот приходит новый разработчик. Он знает только о сервисе в целом, никакую старую аналитику он читать не будет, сразу полезет в код - в итоге многие названия покажутся ему непонятными. Общий принцип - называйте так, чтобы назначение кода было понятно новому разработчику. А любые более менее сложные условия выносите в методы с говорящими названиями. За подробностями - снова порекомендую книгу "Чистый код" Мартина.
#arch #patterns #solid
Telegram
(java || kotlin) && devOps
Всем привет!
Давно хотел написать про паттерны/шаблоны программирования. Основной вопрос, возникающий при разговоре про паттерны - какая от них польза? Ведь главное - умеет человек кодить или нет.
С одной стороны паттерны - это лишь часть арсенала программиста.…
Давно хотел написать про паттерны/шаблоны программирования. Основной вопрос, возникающий при разговоре про паттерны - какая от них польза? Ведь главное - умеет человек кодить или нет.
С одной стороны паттерны - это лишь часть арсенала программиста.…
👍3