Первая работа: почему так сложно найти?

Самое сложное для человека, который изучал программирование некоторое время, найти свою первую работу.

Сложно это по многим причинам. И я попробую объяснить новичкам, как процесс поиска работы джуниором выглядит изнутри.

Резюме


Представьте, что вы работодатель, который открыл набор людей в свою компанию. Заходите на Head Hunter. Там — десятки, а то и сотни объявлений от соискателей. У каждого есть как минимум одно резюме, у самых инициативных — больше. Еще столько же откликнулось на вашу вакансию. Читаем:

Java, HTML, ООП, Английский язык, C/C++, грамотная и поставленная речь, Android

Вы бы взяли такого человека? Я бы — никогда. Америку я не открою, сказав, что резюме — это самая важная часть в поиске работы. Еще раз — САМАЯ важная. Это 80% успеха. Это ваш билет на поезд. Может быть вы и не доедете куда хотели, но поездка не оставит вас без новых впечатлений.

Уже на момент просмотра списка кандидатов, заметьте — списка, а не самого резюме, — решается судьба ищущих. Нет фото, не указана зарплата, которую хотелось бы получать — и вас не заметят.



Запрашиваемая зарплата не соответствует опыту? Программист-все-умею-и-могу? Но мы ищем Java специалиста и знаем, что человек с опытом работы 5 лет не может запрашивать 40 тысяч в Питере.

Итак, ваше резюме — это ваша валюта. Ее стоимость пропорциональна времени, в нее вложенному. Резюме сложное, продуманное, интересное — большой спрос.

В ключевые навыки пишем только то, что делаем лучше всего. Ищем работу Java-программистом — вписываем только Java и все, что к ней относится напрямую. C++ — это хорошо, но не в ключевых навыках, а в разделе «Дополнительная информация», с обязательным указанием, что имели некоторый опыт, знакомы с данной технологией, есть теоретическая подготовка в чем-либо.

Не нужно врать и вписывать то, что не знаете. Спасите себя от позора на собеседовании, пожалейте работодателя и сэкономьте его время. Если список знаний маленький — значит стоит подготовиться еще немного.

Эффекта разорвавшейся атомной бомбы просмотров резюме можно достичь, указав ссылку на личный git аккаунт.
Даже если там тестовое задание с калькулятором для компании N. HR не понимает код, но ей сказали, что ссылка на репозиторий — это круто. Пожалуй, круче только опыт работы, но пока у нас его нет.

Самоучкам, на мой взгляд, сложнее. Да, часто слышно, что «вышка» необязательна. Но это не значит, что ее игнорируют. В теории, да и на практике, человек с профильным образованием имеет хотя бы теоретические знания, прошел курс математики. А это несомненный плюс перед самоучкой, знания которого хаотичны и неполны. Из личного опыта — не взяли на стажировку в Mail.ru, т.к. они обязаны были заключать договор с институтом. То есть даже без образования, являясь лишь студентом, вам могут быть открыты дороги туда, куда нет доступа самоучкам.

Отклики

Несмотря на то что вам ну очень хочется попасть на свою первую работу, не стоит откликаться на все подряд. Вам точно хочется работать в финансовой сфере? А в генетике? Интересен front или только back? Готовы отсидеть полгода в тестировании? Уверены, что не попросят больше? Хуже, чем быть безработным, только заниматься тем, что не нравится.

Внимательно читайте требования к соискателю. Так же, как большинство работодателей игнорируют «программиста-все-умею-и-могу», так и вы опасайтесь компаний, где указан компот из языков и различных технологий.

Почитайте отзывы о компании в интернете, найдите сайт, если есть. Давно ли открылась компания? Государственная или западный филиал? Если знаете английский, то поищите компанию, выполняющую заказы для иностранных клиентов. Это может пригодиться в будущем для потенциального переезда заграницу.

Собеседование

Самая неоднозначная часть в поисках. В разных компания проходит по-разному. Кто-то предпочитает скайп, кто-то личное присутствие. Первая встреча может быть только с HR. Бывает, что несмотря на хороший опыт работы, только по личному неприятию вас девушкой, просто «потому что», вы даже не дойдете до технических специалистов.

Вопросы тоже разные. На моем первом собеседовании были простейшие вопросы по Java SE. Методы Object класса, коллекции, базовое понимание ООП. На других — от «Как бы вы узнали, в случае больших задержек в работе приложения, что именно не оптимизировано?» до «Что такое Java EE, Spring, контейнер в нем же?» или просьб написать свой алгоритм StringBuilder.reverse(). Об этом написано много и это не самое главное.

А главное это то, что вы можете узнать для себя о компании. Некоторые собеседующие обращаются к вам на «Вы», к вашим промахам терпеливы, пытаются помочь выйти из затруднения подсказками, понимая, что вы волнуетесь. Другие — откровенно смеются во весь голос вам в лицо. Третьи просят сделать откровенный бред, вроде «Напишите по памяти на листке бумаги сортировку пузырьком», что у меня вызывает недоумение, так как не могу представить где и для чего использовать этот алгоритм. При этом они отказываются от вашего предложения написать сортировку слиянием взамен.

Собеседование в компании, где я сейчас работаю, было достаточно простым, недолгим и очень приятным. За примерно 20 минут меня спросили о моем опыте программирования, проектах в которых участвовал, кто я в целом такой. Общие вопросы вширь. В конце сказали: «Вот вам тестовое задание. Залить на гит и описаться на почту в течение такого-то срока. Вам ответят тогда-то.». Позже я узнал, что вместе со мной пытались устроиться еще несколько студентов/выпускников. Кто-то некрасиво вел себя во время собеседования, а кто-то просил зарплату больше, чем я (40000р.), при этом выполнив задание не до конца или хуже. В итоге я попал в невероятно уютный коллектив с классным начальником и удобным ритмом работы.

После/до технической части у вас будет возможность задать вопросы о компании. Обязательно нужно спрашивать следующее:

  • На какой проект вас поставят
  • Версия Java и технологии проекта
  • Будете вы разработчиком или тестировщиком (первое время)
  • Ваши обязанности/характер работы (fullstack, back)
  • Зарплата (если в вакансии не было указано), льготы, бесплатные плюшки (от кофе до книг и курсов)
  • Когда будет дан ответ приняты вы или нет (добивайтесь точной даты)
  • Misc: График, митинги, обед, отпуск и больничный и их оплачиваемость etc.

Подведем итог. Может быть не совсем прозрачно, но я хотел вам показать, что нет универсальных ситуаций того, как проходят собеседования. Еще раз, я очень советую вам не гнаться за всеми вакансиями подряд, вести себя нетерпеливо из-за изнывающего «лишь бы взяли». Ваш вклад в резюме и профиль на github могут устроить вас в компанию мечты с адекватными условиями работы, коллективом, «резиновыми» часами работы и атмосферой, в которой вы будете профессионально расти как тесто на дрожжах. Рассылая же сотни резюме, вы рискуете попасть лишь в какую-то там компанию.

Напоследок обширная и более подробная статья по теме от mail.ru.

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

Не нашёл ответов на вопросы собеседований из уровня 37 - выкладываю свои

Здравствуйте. Опять-таки, не нашёл ответов и на эти вопросы. Решил выложить ответы, которые я составил для себя.

Вот, собственно вопросы:
Вопросы к собеседованию:
1. Что такое паттерны проектирования?
2. Какие паттерны проектирования вы знаете?
3. Расскажите про паттерн Singleton? Как сделать его потокобезопасным?
4. Расскажите про паттерн Factory?
5. Расскажите про паттерн AbstractFactory
6. Расскажите про паттерн Adaper, его отличия от Wrapper?
7. Расскажите про паттерн Proxy
8. Что такое итератор? Какие интерфейсы, связанные с итератором, вы знаете?
9. Зачем нужен класс Arrays?
10. Зачем нужен класс Collections?

А вот мои ответы:
Мои ответы:

1. Паттерны проектирования — это устоявшиеся удачные решения самых распространнёх проблем, возникающих при проектировании и разработке программ или их частей.

2. Singleton, Factory, Abstract Factory, Template method, Strategy, Pool, Adapter, Proxy, Bridge, MVC.

3. Когда нужно, чтобы в программе существовал только один экземпляр какого-то класса, то применяют паттерн Singleton. Он выглядит так (lazy initialization):
clas Singleton {
private Singleton instance;
private Singleton() {}
public static Singletot getInstance() {
if (instance == null)
instance = new Singleton();
return instance;
}
}

Чтобы сделать его потокобезопасным, можно добавить к методу getInstance() модификатор synchronized. Но это будет не самым лучшим решением (зато самым простым). Гораздно лучшее решение — это написать метод getInstance таким образом (double-checked locking):
public static synchronized Singleton getInstance() {
if (instance == null)
synchronized(Singleton.class) {
instance = new Singleton();
}
return instance;
}

4. Паттерн Factory — это порождающий паттерн. Он позволяет создавать объекты по требованию (например, при определённых условиях). Выглядит это так:
class Factory{
public static Object1 getObject1() {
return new Object1();
}

public static Object2 getObject2() {
return new Object2();
}

public static Object3 getObject3() {
return new Object3();
}
}

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

class FactoryMethod {
public enum TypeObject {
TYPE1,
TYPE2,
TYPE3
}

public static CommonClass getObject(TypeObject type) {
switch(type) {
case TYPE1:
return new Object1();
case TYPE2:
return new Object2();
case TYPE3:
return new Object3();
default:
return null;
}
}
}

Классы Object1, Object2 и Object3 наследуются от класса CommonClass.

5. Паттерн Abstract Factory — это также порождающий шаблон проектирования. Согласно этому паттерну, создаётся некоторая абстрактная фабрика, служащая шаблоном для нескольких конкретных фабрик. Можно привести такой пример:
class Human {}

class Boy extends Human {}
class TeenBoy extends Human {}
class Man extends Human {}
class OldMan extends Human {}

class Girl extends Human {}
class TeenGirl extends Human {}
class Woman extends Human {}
class OldWoman extends Human {}

interface AbstractFactory {
Human getPerson(int age);
}

class FactoryMale implements AbstractFactory {
public Human getPerson(int age) {
if (age < 12)
return new Boy();
if (age >= 12 && age <= 20)
return new TeenBoy();
if (age > 20 && age < 60)
return new Man();
return new OldMan();
}
}

сlass FactoryFemale implements AbstractFactory {
public Human getPerson(int age) {
if (age < 12)
return new Girl();
if (age >= 12 && age <= 20)
return new TeenGirl();
if (age > 20 && age < 60)
return new Woman();
return new OldWoman();
}
}

6. Паттерн Adapter — это структурный паттерн. Его реализация позволяет использовать объект одного типа там, где требуется объект другого типа (обычно это абстрактные типы). Пример реализации этого паттерна:
interface TotalTime {
int getTotalSeconds();
}
interface Time {
int getHours();
int getMinutes();
int getSeconds();
}

class TimeAdapter extends TotalTime {
private Time time;
public TimeAdapter(Time time) {
this.time = time;
}
public int getTotalTime() {
return time.getSeconds + time.getMinutes * 60 + time.getHours * 60 * 60;
}
}

class TotalTimeAdapter extends Time {
private TotalTime totalTime;
public TotalTimeAdapter(TotalTime totalTime) {
this.totalTime = totalTime;
}

public int getSeconds() {
return totalTime % 60;
}

public int getMinutes() {
return (totalTime / 60) % 60;
}

public int getHours() {
return totaltime/ (60 * 60);
}
}

class Main {
public static void main(String[] args) {
Time time = new Time() {
public int getSeconds() {
return LocalTime.now().getSecond();
}

public int getMinutes() {
return LocalTime.now().getMinute();
}

public int getHours() {
return LocalTime.now().getHour();
}
};

TotalTime totalTime = new TimeAdapter(time);
System.out.println(totalTime.getTotalSeconds());

TotalTime totalTime2 = new TotalTime() {
public int getTotalSeconds() {
LocalTime currTime = LocalTime.now();
return currTime.getSecond() + currTime.getMinute * 60 + currTime.getHour * 60 * 60;
}
};

Time time2 = new TotalTimeAdapter(totalTime2);
System.out.println(time2.getHours + ":" + time2.getMinutes() + ":" + time2.getSeconds());
}
}

При реализации паттерна Wrapper создаётся класс, который оборачивает исходный класс и реализует тот же интерфейс, который реализует исходный класс. Таким образом, это позволяет расширить функциональность исходного класса и использовать новый класс там, где ожидается использование исходного класса. Это отличается от реализации паттерна Adapter тем, что в данном случае используется один интерфейс (тот же, что есть у исходного класса). В паттерне Adapter же используется два интерфейса, и класс, который оборачивает экземпяр исходного класса, реализует совсем другой инферфейс, не интерфейс исходного класса.

7. Паттерн Proxy — это структурный паттерн проектирования. Он нужен для того, чтобы контролировать доступ к какому-то объекту. Для этого пишется класс по типу «обёртка», то есть внутрь класса передаётся исходный объект, реализующий некий интерфейс, сам класс тоже реализует этот интерфейс, и в каждом методе этого класса вызывается похожий метод у исходного объекта. Реализация того же интерфейса, что и у исходного объекта, позволяет подменить исходный объект прокси-объектом. Также это позволяет, не меняя исходного объекта, «навешивать» на его методы какуют-то специальную дополнительную функциональность (например, логирование, проверка прав доступа, кэширование и т.д.). Пример:
interface Bank {
void setUserMoney(User user, double money);
double getUserMoney(User user);
}

class CitiBank implements Bank { //оригинальный класс
public void setUserMoney(User user, double money) {
UserDAO.update(user,money);
}

public double getUserMoney(User user) {
UserDAO.getUserMoney(user);
}
}

class SecurityProxyBank implements Bank {
private Bank bank;

public SecurityProxyBank(Bank bank) {
this.bank = bank;
}
public void setUserMoney(User user, double money) {
if (!SecurityManager.authorize(user,BankAccounts.Manager)
throw new SecurityException(«User can't change money value»);

UserDAO.update(user,money);
}

public double getUserMoney(User user) {
if (!SecurityManager.authorize(user,BankAccounts.Manager)
throw new SecurityException(«User can't get money value»);

UserDAO.getUserMoney(user);
}

8. Итератор — это специальный внутренний объект коллекции, который позволяет последовательно перебирать элементы этой коллекций. Этот объект должен реализовывать интерфейс Iterator, либо ListIterator(для списков). Также, для того, чтобы перебирать элементы коллекции, коллекция должна поддерживать интерфейс Iterable. Интерфейс Iterableсодержит всего один метод — iterator(), который позволяет извне получить доступ к итератору коллекции. Интерфейс Iteratorсодержит следующие методы:

boolean hasNext() — проверяет, есть ли в коллекции ещё какой-то элемент
E next() — позволяет получить очередной элемент коллекции (после получения элемента, внутренний курсор итератора передвигается на следующий элемент коллекции)
void remove() — удаляет текущий элемент из коллекции

Интерфейс же ListIteratorсодержит такие методы:
boolean hasNext() — проверяет, существуют ли ещё один элемент в коллекции (следующий за текущим)
E next() — возвращает очередной элемент коллекции (и передвигает внутренний курсок итератора на следующий элемент)
int nextIndex() — возвращает индекс следующего элемента
void set(E e) — устанавливает значение текущего элементаvoid add(E e) Добавляет элемент в конец списка.
boolean hasPrevious() — проверяет, существует ли какой-то элемент в коллекции перед данным элементом
E previous() — возвращает текущий элемент коллекции и переводит курсор на предыдущий элемент коллекции
int previousIndex — возвращает индекс предыдущего элемента коллекции
void remove() — удаляет текущий элемент коллекции
void add(E e) — добавляет элемент e после текущего элемента коллекции

9. Класс Arrays — это утилитарный класс, предназначенный для разнообразных манипуляций с массивами. В этом классе есть методы превращения массива в список, поиска по массиву, копирования массива, сравнения массивов, получения хешкода массива, представление массива в виде строки и др.

10. Класс Collections — это утилитарный класс для работы с коллекциями. В этом классе есть методы добавления элементов в коллекцию, наполнения коллекции элементами, поиска по коллекции, копировании коллекции, сравнения коллекции, нахождения максимального и минимального элементов коллекции, а также методы получения специфический модификаций коллекций известных типов (например, можно получить потокобезопасную коллекции или неизменяемую коллекцию с одним элементом).

Тестовое задание: Управление пользователями (Junior Java Developer, стажёр)

Необходимо разработать веб-приложение, позволяющее управлять пользователями
(создавать, редактировать, просматривать список и детали, удалять)

Функциональные требования к веб-приложению:
  1. Наличие RESTful интерфейса;
  2. Поддержка операций управления (создания, чтения, редактирования и удаления) пользователями.
    Пользователь определяется следующими значениями:
    • Имя
    • Фамилия
    • Дата рождения
    • Логин
    • Пароль
    • Поле ввода “О себе”
    • Адрес проживания
  3. Наличие пользовательского WEB-интерфейса

Нефункциональные требования:
  • JEE стек технологий
  • Фреймворки, библиотеки: Hibernate, Spring
  • Система хранения данных: PostgreSQL
  • Код приложения необходимо снабдить комментариями
  • Приложение должно собираться при помощи maven без установки или настройки каких либо дополнительных компонент;
  • Архив с результатом тестового задания должен содержать текстовый файл readme.txt с инструкцией по сборке, настройке, конфигурированию и развертыванию приложения (если необходимо).

Вопрос на засыпку

Кто может, не залезая в ИДЕЮ, сказать, что выдаст в консоль следующий код и почему? :)

class Feline {
    public String type = "f ";
    public Feline() {
        System.out.print("feline ");
    }
}
public class Cougar extends Feline {
    public Cougar() {
        System.out.print("cougar ");
    }
    public void go() {
        type = "c ";
        System.out.print(this.type + super.type);
    }
    public static void main(String[] args) {
        new Cougar().go();
    }
}

36 уровень - тоже не нашёл ответы на вопросы из собеседований.

Опять-таки всё перерыл, ответов не нашёл. Что ж. Выложу свои, хотя я писал их чисто для себя, и по возможности — кратко. Но всё лучше, чем ничего. Итак, были такие вопросы:
Вопросы к собеседованию:
1. Что такое MVC?
2. Что такое DAO и DTO?
3. Что такое POJO?
4. Что такое Entity?
5. Какие коллекции-списки вы знаете?
6. Какие коллекции-множества вы знаете?
7. Что такое map, чем он отличается от «словаря»?
8. Что такое Queue и Dequeue?
9. Какие классы, реализующие интерфейс Queeue вы знаете?
10. Что такое дерево?

А теперь мои ответы:
1. MVC — это такой паттерн проектирования приложение, при котором приложение разделяется на три отдельные части: модель (model), представление (view) и контроллер (controller). Модель предоставляет данные и реагируется на команды контроллера, изменяя своё состояние. Представление отвечает за отображение данных модели пользователю, реагируя на изменения модели. А контроллер интерпретирует действия пользователя, оповещая модель о необходимости изменений. Таким образом каждый из компонентов этой схемы слабо связан с другими компонентами, за счёт чего достигается гибкость программы. Чаще всего вся бизнес-логика размещается в модели, хотя иногда она содержится и в контроллере. В первом случае модель называют тонкой, в последнем — толстой.

2. DAO (Data Access Object) — это объект, основная задача которого сохранять данные в базу данные, а также извлекать их из неё. DTO (Data Transfer Object) — это объект, предназначенный для транспортировки данных. Поэтому его основная задача — хранить эти данные. Никакой логики он не содержится. Кроме того, он должен быть сериализуемым, так как транспортировка объектов обычно происходит с помощью сериализации-десериализации.

3. POJO переводится как «объект Java в старом стиле». Их противопоставляют EJB-объектами. Последние следуют специальной конвенции и обычно жёстко привязаны к какому-то конкретному enterprise-фреймворку (например, у них должен быть публичный конструктор без параметров, должен быть геттеры и сеттеры для полей, они должны быть сериализуемыми и т.д.). POJO — это, соответственно, обычный класс, не наследующий ни от каких специальных классов и не реализующий никаких специальных библиотек. Обычно POJO ничего особенного не делает, и содержит только состояние.

4. Entity Bean – это бин, цель которого хранить некоторые данные. В логику такого бина встроен механизм сохранения себя и своих полей в базу данных. Такой объект может быть уничтожен, а потом воссоздан из базы заново. Но кроме хранения данных у него нет никакой логики. А бин в свою очередь — это особый класс, которые должен выполнять следующие правила:
а) Класс должен иметь конструктор без параметров, с модификатором доступа public. Такой конструктор позволяет инструментам создать объект без дополнительных сложностей с параметрами.
б) Свойства класса должны быть доступны через get, set и другие методы (так называемые методы доступа), которые должны подчиняться стандартному соглашению об именах. Это легко позволяет инструментам автоматически определять и обновлять содержание bean’ов. Многие инструменты даже имеют специализированные редакторы для различных типов свойств.
в) Класс должен быть сериализуем. Это даёт возможность надёжно сохранять, хранить и восстанавливать состояние bean независимым от платформы и виртуальной машины способом.
г) Класс должен иметь переопределенные методы equals(), hashCode() и toString().

5. Все коллекции-списки реализуют интерфейс Listи наследуются от абстрактного класса AbstractList. Среди них можно выделить ArrayListи LinkedList. ArrayList — это список, основаный на массиве, а LinkedList — это классический двусвязный список.

6. Коллекции-множества в Java реализуют интерфейс Setи наследуются от AbstractSet. Множества — это такие наборы данных, в которых все элементы уникальны. Среди них в Java есть HashSet, LinkedHashSet и TreeSet. Первая коллекция хранит свои объекты на основе хеш-кодов. Вторая — это модифицированная первая, в ней элементы ещё к тому же располагаются в связном списке, поэтому они все расположены в порядке добавления. Третья коллекция обеспечивает сортировку своих элементов.

7. Map — это вид коллекций, хранящих свои элементы в виде пар «ключ — значения». Причём все ключи должны быть уникальными. Среди реализаций есть HashMap и TreeMap. Первая реализация хранит элементы с использованием хэш-кодов. Вторая — хранит элементы в отсортированном по ключу порядке.

8. Очередь (Queue) — это структура данных, работающая по принципу «Первый вошёл — первый вышел». То есть элементы в очередь добавляются с одного конца, а извлекаются — с другого. Deque — это двусторонняя очередь. В этой очереди элементы можно добавлять как в начало, так и в конец, а также брать элементы тоже можно и из начала, и из конца очереди. Соответственно есть методы, которые позволяю положить элемент (это методы add(e) и offer(e)), и есть методы, позволяющие извлечь элемент из очереди (это такие методы, как remove() и poll()). Кроме того, есть методы, которые позволяют просто получить элемент из очереди без его удаления оттуда (это методы element() и peek()). В интерфейсе Deque дополнительно есть методы для добавления элементов в начало и конец очереди, извлечения элементов из начала или конца, а также получения элементов из начала или конца очереди (без их удаления из очереди).

9. Среди простых реализаций можно отметить ArrayDeque, LinkedList и PriorityQueue. Также существуют много классов в Concurrent Collections, которые реализуют эти два интерфейса (оба сразу или только один из них).

10. Дерево — это связный граф без петель и кратных рёбер. Обычно, если в дереве N вершин, то количество рёбер как минимум — N-1. Также одну вершину в дереве выбирают в качестве корня. Остальные вершины объявляют ветвями. Ветви, у которых нет своих ветвей, называются листьями дерева.
В программировании деревья используются довольно широко, и придумано уже много видов этого дерева. Одно из самых широкоприменяемых деревьев — это бинарное дерево. В этом дереве у каждого элемента имеется не больше двух потомков (то есть может быть от 0 до 2). Одной из разновидностью двоичного дерева является BST — бинарное дерево поиска. В этом дереве на элементы накладывается правило: левый потомок элемента должны быть по значению меньше его, а правый — по значению больше его или равен ему.
Также ещё существуют красно-чёрные деревья. Это разновидность двоичных деревьев поиска. В красно-чёрных деревьх вводится ещё одно свойство элемента — цвет. Цвет может быть чёрный или красный. Также каждое красно-чёрное дерево должно удовлетворять следующим требованиям:
1) корень дерева — чёрный;
2) узел либо красный, либо чёрный;
3) все листья дерева — чёрные;
4) оба потомка красно узла — чёрные;
5) всякий путь от данного узла до любого листового узла, являющегося его потомка, содержит одинаковое количество чёрных узлов.

Эти правила позволяют добиться сбалансированности дерева. Дерево сбалансированно, когда длина пути от корня до любого листового узла отличается не более, чем на 1. (То есть по-простому, в дереве нет перекосов и длинных ветвей.)

Что-то не нашёл ответов на вопросы из собеседований на 34 левеле

Поискал на сайте родным поиском и с помощью гугла всё облазил — нет ответов на вопросы из этого левела. Может я что-то пропустил, и они всё-такие где-то есть здесь на сайте!?

На всякий случай прикладываю ответы, которые я написал для себя:
Вопросы к собеседованию:
1. Что такое сборка мусора?
2. Когда вызывается метод finalize?
3. Что произойдет, если в методе finalize возникнет исключение?
4. Что такое SoftReference?
5. Что такое WeakReference?
6. Что такое PhantomReference?
7. Как работает WeakHashMap? Где он используется?
8. Зачем нужно передавать очередь в конструктор PhantomReference?
9. Зачем нужен логгер?
10. Какие настройки логгера вы знаете?


Мои ответы:
1. Это механизм уничтожения ненужных объектов. Ненужные объекты — это неиспользуемые объекты. Существует два способа поиска таких объектов: подсчёт ссылок и трассировка. В первом случае с каждым объектом связывается некоторая переменная, которая хранит количество ссылок на этот объект. Если это количество опускается до нуля, то объект считается мёртвым. Во втором случае сборщик мусора идёт по ссылкам объектов из корневых точек до конца (до значения нулл), обходя всё это дерево. Объекты, до которых он не может добраться из корневых точек, считаюся мёртвыми. Корневыми точками считаются все активные нити, метод main, аргументы метода main(), а также все статические переменные класса, в которой находится метод main().
Определение объектов, пригодных к уничтожению — это только первая часть работы сборщика мусора. Вторая часть — это собственно их удаление и работа с памятью. Здесь используется гибридный подход. Вся доступная для объектов память разделяется на три области: область молодых объектов, область старых объектов и область перманентных объектов (это классы, метаданные, интернированные строки и т.д.). Первая область разделяется ещё на три подобласти: на Eden и suvivor space 1 и 2. В Eden хранятся все только созданные объекты. В остальных двух зонах хранятся объекты, выживщие после последней сборки мусора. Сборщик мусора работает со всей этой областью (областью молодых объектов) следующим образом. Во время очередной сборки мусора он находит живые объекты в области Eden и копирует их во вторую область выживших. После этого он в первой области также ищет живые объекты и копирует их либо в вторую область выживших, либо, если они уже достаточно «старые» — область старого поколения. После этого он очищает область Eden и первую область выживших. Дальше он считает вторую область выживших первой. И всё, на это сборка мусора заканчивается для этой области.
Для второй области сборка мусора идёт несколько по-другому. Там есть одна большая область, она ни на что не делится, но сборщик мусора все живые объекты в ней во время своей работы перемещает в начало области. Соответственно, вторая часть области будет состоять только из пустого пространства и мёртвых объектов. После этого сборщик мусора завершает свою работу.

2. Перед уничтожение объекта сборщиком мусора. Также можно вручную запустить вызовы этого метода у всех недостижимых объектов, для этого надо вызвать метод System.runFinalization() или Runtime.getRuntime().runFinalization().

3. Это исключение будет проигнорировано, и произойдёт выход из метода.

4. SoftReference переводится как «мягкая ссылка». Эта ссылка на объект, но более слабая, чем обычная ссылка (StrongReference). Объекты, на которые сущесвуют только мягкие ссылки, называются мягкодостижимыми. Такие объекты не уничтожаются в обычном случае. Но если у JVM закочиналась память, то сборщик мусоры удаляет все такие объекты.

5. WeakReference — это так называемая слабая ссылка на объект. Она ещё слабее Soft-ссылки. Все объекты, на которые существуют только слабые ссылки, будут удалены при ближайщей сборке мусора.

6. PhantomReference — это самая слабая ссылка. Механизм работы с такими ссылка запускается только если на объект нет больше никаких других ссылок. Призрачные ссылки используются для сложной процедуры удаления объекта. Это может быть необходимо, если объект делает что за граница Java-машины, например, вызывает низкоуровневые функции ОС или пишет своё состояние в файл, или делает ещё что-то важное и сложное.
Механизм работы с такими ссылками следующий. Если на объект не осталось больше никаких других ссылок, и у него переопределён метода finalize(), то этот метода будет вызван во время ближащей сборки мусора. Если же этот метод не переопределён, то этот объект пропускает текущую сборку мусора, и попадает только в следующую. Во время этой (следующей) сборки мусора данный объект помещается в очередь призрачных объектов, из которой будет удалён, когда у его призрачной ссылки вызовут метод clear(). Также стоит отметить, что метода get() у призрачной ссылка всегда возвращает null (в отличие от двух других несильных ссылок, у которых он возвращает null, только если объект уже уничтожен).

7. WeakHashMap — это HashMap, у которого ключами являются слабые ссылки. Поэтому, если во время ближайшей сборки мусора будет обнаружено, что на объект существует только ссылка в WeakHashMap, то из WeakHashMap будет удалена вся пара «ключ-значение», связанная с этим объектом.
В связи с этим данная коллекция может быть использована для хранения какой-то дополнительной, не очень важной информации об объекте. Также её удобно использоваться для хранения какой-то временной информации (которая нужная только в рамках данной операции).

8. Эта очередь используется для отслеживания того, что объект больше не нужен. Может быть использовано для закрытия ресурсов, открытых данным объектом (например, удаление созданных файлов).

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

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

Написал игру на Java в 14 лет.

Предыстория
В младших классах я очень любил компьютерные игры. Со временем у меня все больше и больше появлялось желание
создать что-то свое. Я узнал об одной очень интересной профессии — Программист. Программист, в моем понимании творец, писатель в своем роде, он может создать что захочет, написав строчки кода. Я сразу же загорелся желанием стать им. К тому же, зарплата у программистов довольно высокая.
Начало
Первым, как я считал «языком программирования» для меня стал html. Я изучил его примерно за несколько недель. Дальше css, и тут меня занесло в этот неизведанный мир… Я начал верстать простые страницы, делать прототипы сайтов, сидел на разных форумах, в общем мне все это безумно нравилось.
Как я познакомился с Java
У меня был выбор, идти дальше изучать веб, или пойти в ПО программирование. Я выбрал ПО. Начал искать курсы облазил весь гугл и нашел JavaRush. Очень зацепили фишки, что курс построен в виде игры, и что во время обучения присутствует юмор. Примерно за месяц прошел первые 10 уровней. Потом нужно было покупать подписку, но я так и не решился. К следующему НГ я понял, что нужно что-то менять, и купил долгожданную подписку. С этого момента я решил серьезно заниматься. На данный момент мне 14 лет, я достиг 27 уровня. Недавно захотелось написать что-то самому, с нуля. И у меня это получилось. Я написал игру GetFoodGame. Для запуска дважды кликните по файлу GetFoodGame.jar. Идея такова: сверху падают фрукты а игрок, управляю вазой с помощью стрелочек (Влево, Вправо) ловит их. Когда вы не смогли поймать 2 фрукта, появляется окошко, с надписью что вы проиграли. По моему мнению, реализовал я не очень хорошо (мягко говоря) слишком много костылей. Буду рад конструктивной критике ;) Всем хорошего настроения, и успехов !)
  • ,

Объясните пожалуйста, почему не проходит проверку?

Требования:
1. Программа должна считывать данные с консоли.
2. Программа должна вывести на экран все четные числа считанные из файла отсортированные по возрастанию.
3. Программа должна выводить данные на экран.
4. Программа должна закрывать поток чтения из файла(FileInputStream).

public class Solution {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            BufferedReader bf = new BufferedReader(new InputStreamReader(new FileInputStream(reader.readLine())));
            while (bf.ready()){

                   String s = bf.readLine();
                   if(!s.equals("")){
                       int number = Integer.parseInt(s);
                       if (number % 2 == 0 && number > 0) list.add(number);
                   }
            }
            bf.close();
            reader.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        Collections.sort(list);
        for (int i : list)
        {
            System.out.println(i);
        }
    }
}
  • ,

В девелопмент через тестирование.

Я не писатель, я инженер.

Моя история началась 7 лет назад в городе-герое Минске.

Интро
Сам я родом из небольшого районного центра в 100 км от столицы РБ, куда и вернулся после получения диплома специалиста по телекоммуникациям.
На тот момент я немного знал и умел верстать статические HTML страницы с небольшими примесями JS. Уверенность в то время еще придавали умение обращаться с PC и навыки слепого набора на RU и EN расскладках. (да, я был наивен и не сведущ). Очень хотелось устроится Web-верстальщиком.
С английским вообще была беда: понимание текста — pre-intermediate в лучшем случае, а понимание на слух, разговорный и письмо — полное дно.

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

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

Ожидание
Первых 3 месяца (конец весны и почти все лето) ответов не было вообще. Моя уверенность в правильности выбора уже улетучилась. Из средств на существование — дохленькая зп жены, которой еле-еле хватало на еду и возмещение долга. И вот в конце августа моему счастью не было предела — 2!!! компании откликнулись на мое резюме.

Предложения
#1: Первое письмо было, можно так сказать, ни о чем — заброс удочки живой я еще или нет. На мой ответ, что я все еще ищу работу, мне было предложено попробовать пройти обучение в компании в течение 3 месяцев (5 дней в неделю по 6 часов), по итогам которого будет принято решение, достоинен ли я. Учитывая мое финансовое положение и удаленность моего места жительства от столицы — сразу отправили это предложение «ф топку».
#2: Второе письмо оказалось приглашением на собеседование.

Судьба?
В «офис» (пару комнат в каком-то складском здании, многие из которых на то время мне показались чем-то похожими на актовые залы) я приехал слишком заранее (спасибо «хорошо развитой» междугородной системе ОТ). До собеседования на должность верстальщика я так и не дошел. Дабы мне не мозолить глаза сотрудникам и не ждать в одиночестве, HR-специалист предложила мне попробовать пособеседоваться на должность QA-инженера. Кто такие тестировщики, я понятия не имел, но девушки, проводившие собеседование, так упоительно расписывали все прелести работы QA-специалиста, что я решился на беседу. Беседа была не долгой: минут 10-15 они пытались понять что я знаю и умею, еще минут 10 они рассписывали прелести направления и проект, на который ищут человека. Долгим было тестовое задание: мне дали «потыкать» разарабатываемое Web-приложение (это я сейчас знаю, что это была оттестированная версия, в которой имелись известные баги, которые, собственно, я и должен был найти). Явилась ли эта беседа причиной того, что собеседование на должность верстальщика со мной перенесли на другую дату, или это просто случайное совпадение, но домой я уезжал полный впечатлений и с обещанием девушек связаться со мной втечение двух ближайших недель с результатами нашей беседы. Еще более удивительным было письмо с предложением позиции junior test engineer, пришедшее уже на следующий день. Понятное дело, что ждать собеседование на верстальщика я уже не стал, а в тестировщики пошел с надеждой и верой, что работая в IT уже легче прокачиваться и перемещаться.
Как мне рассказали уже спустя год — такое быстрое предложение было вызвано тем, что я нашел серьезные баги, которые пропустила их QA команда. В довесок им понравились мои знания верстки.

Карьерный рост, или когда же?
#1. Еще не Junior.
Все началось с испытательного срока. По условиям контракта — испытательный срок 3 месяца, с выплатой 50% от договоренной зп (это был мой первый опыт получения зарплаты в конверте :) ). Во время испытательного срока — интенсивные курсы QA инженера. Каждый день 1-2 тестовых задания: приложения в которых нужно найти как можно больше багов. Были и взлеты и падения. Каждое рабочее утро у меня начиналось с подъема в 6.00, быстрого завтрака и 2 часовой езды на ОТ. 9 часов работа с перерывом на обед и 2 часа обратной дороги домой. Первой зп еле хватило на покрытие транспортных расходов. Был и не приятный момент: на одном из тестовых заданий я очень сильно «засыпался», набрал всего 10% — даже ставился вопрос о прекращении дальнейшего сотрудничества. Договорились еще пару недель потренировать меня, а уже потом принимать решение. Испытательный срок закрыли досрочно. За 2 месяца интенсивных тренировок меня превратили в…

#2. Junior Test Engineer.
Для меня, как для человека приехавшего из глубинки и до этого работавшего на гос. контору, все в IT было в диковинку. Особенно непривычным было отношение в компании к сотрудникам. Никто на тебя не орет без повода, у всех есть конкретные задачи, никто не контролирует тебя по 10 раз на дню. Я попал в рай… Но по мере роста моих навков, я начал опускатья на землю. Вся учеба сводилась к тренировкам в тестировании, написании тестовых сценариев, оформлению багов и изучению английского. В общем благодаря первым пунктам изучать английский получалось так себе. Изучать же что-то в девелопменте не получалось вообще. Вот таким мне запомнился мой первый год в IT.

#3. Test Engineer.
Прошел почти год. Приставка junior «отвалилась», немного выросла зп. За зиму очень сильно задолбало по 4 часа в день тратить на дорогу. На семейном совете было принято решение перебираться в столицу. К концу лета сняли однокомнатную квартиру на окраине в старой хрущевке. По аренде как раз смогли вписаться в мой бюджет на дорогу. Снова жизнь на одну зп, т.к. у жены поиски с работой не клеились еще похлеще моих. Прошла эйфория от устройства в IT. Завершился «мой» первый проект (к слову не удачно, прогорел), команду расформировали по другим проектам. Вот тут я в полной мере ощутил, что такое сидеть на «бэнче» для тестировщика. Если разработчик сидя на «бэнче» прокачивает свои скилы, посещая различные курсы и просматривая различные видео, то «скамейка» тестировщиков — это полный «трэш». Тебя пихают во все проекты где нужна помощь. За неделю ты можешь поучавствовать в тестировании 2-3 проектов. Начали появлять негативные эмоции… Незаметно подкралась зима… Новый 2011 год!
Через пару недель после НГ, ко мне в личку постучался коллега, недавно перешедший в другую контору. Им на проект нужен был срочно тестировщик. Он предлагал мне пройти собеседование. Собеседование было чисто формальным. Спросили умею ли я писать sql запросы, дали 2-3 задания на написание запросов с использованием JOIN. Спросили на какую зп я согласился бы перейти к ним.
Дали на 25% больше — я почти не думал над принятием решения о переходе. Новая компания, новый проект, большой, я бы даже сказал, огромный. Более 200 членов команды только в Минске. Приятным бонусом оказались командировки в Москву и ежеквартальные денежные бонусы. Жизнь стала налаживаться, жена нашла хоть и не высокооплачиваемую работу, но по душе. С долгами расчитываться стало веселей. В новой компании опять пришлось проходить обучение (которое заняло 3 месяца), тоже был испытательный срок, который закрыил уже через месяц. ЗП на испытательном сроке не урезали.

#4. Middle.
В разных компаниях эту позицию называют по разному (middel, senoir, вообще без приставки), но в большинстве это как раз серединная позиция. 3+ года опыта работы в IT. Мне удалось закрепиться в отрасли. К моему мнению стали прислушиваться. Появилось немного времени на обучение. Этой компании я благодарен за курсы английского языка. После 2-х лет занятий я стал немного понимать язык на слух, без проблем читать техническую документацию по проекту, начал местами понимать статьи в англязычных газетах. Спустя год проект закрылся, такую большую команду не так-то легко разместить по другим проектам. Разработчикам предложили пройти переподготовку на Java. Т.к. я все равно находился на «бэнче», мне удалось уговорить ПМ-а записать и меня на эти курсы. Так состоялось мое первое знакомство с Java. Длилось оно не долго — 4 занятия. Причины две: курс был расчитан на разработчиков с опытом работы 3+ года, и меня перевели на новый проект. На новом проекте помимо ручного тестироваиня, я соприкоснулся с автоматизированными тестами. Тесты писались на Delphi-script :). Через пол года на новом проекте начали урезать бюджет, я как последний пришедший — стал первым ушедшим. Опять «бэнч»… и ожидание пополнения в семье.

#5. A как живут мидлы в Европе?
В один из апрельских дней я как-то повстречал одно из коллег еще по первому проекту. Мы разговорились. Коллега уже год как работал в Риге, был очень доволен переездом. Потом, шутя предложил мне написать резюме и передать ему. Я написал какую-то ерунду (не писатель я, а инжинер) на одну страницу. Через неделю раздался звонок с не беларусского номера. Меня приглашали побеседовать через Skype. Была не была. Беседа велась на русском. Просто пообщались за жизнь. HR с той стороны предложил попробовать пройти собеседование на новый стартующий проект.
Все прошло очень быстро. Через 2 дня беседа с HR: вот тут по моим знаниям прошлись «танком», благо на русском. Так же проверили уровень моего разговорного английского. Еще через 2 дня техническое собеседование — 10 заданий и 30 минут времени, все это онлайн (я дома перед компом, они толпой на другом конце «провода»). Через неделю я получил офер. Запустился процесс оформления документов. Через месяц я стал папой. Еще через месяц я прогуливался по старым улочкам Риги и не мог поверить в произошедшее. Еще 4.5 года назад я был простым безработным парнем, с огромным долгом перед государством. Да, с долгом удалось без проблем рассчитаться перед началом оформления документов.
Старт нового проекта дал возможность прокачаться в автоматизации. Т.к. первых 3-4 месяца тестировать было особо нечего, руководство проекта приняло решение осваивать автоматизацию Selenium + Nodejs (не слишком популярный стек на то время). Так я стал автоматизатором. за 3 года на проекте я создал свой фреймворк с нуля, успел его уже дважды переписать.

#6. Lead.
На волне успешного проекта по автоматизации я взял еще одну высоту. За это время успел 2 раза отказаться от позиции team lead (не люблю я митинги, мне нравится возиться с кодом). Обучил своего первого падавана :). Провел несколько собеседований на позицию тестировщика. Но все это не то, к чему я когда-то стремился.

Ну как же без его величества, случая
Летом 2016 я случайно наткнулся на проект javarush.ru, первых 10 уровней пролетел за 2 вечера. Аппетит приходит во время еды, тем более отпуск на носу. О! да тут еще и скидка на год…
В общем вторую десятку уровней осилил за 2 недели отпуска в горах. Осень… Загрузка на проекте, рождение второго ребенка, оформление документов, а еще и грядущий апдейт 2.0 — перерыв на 3 месяца. НО! перерыв только для javarush, но не для JAVA. После отпуска я не давал покоя коллегам из серверной команды, задавая им вопросы по непонятным темам с javarush, показывал им куски своего кода, рассказывал свои логические решения, «подсматривал» их код в репозитории. Моя активность не осталась не замеченой. В конце ноября лид серверной команды предложил мне попробовать свои силы в Java EE на благо проекта. Для начала это были пробные шаги — 1-2 дня в неделю. К весне — 50/50 junior java developer/lead test engineer. По весне собрав всю волю в кулак — мужественно до 2-3 часов ночи продолжил свои сражения на полях javarush.

Эпилог
На сегодняшний день я работаю в проекте средней величины. 75% времени — я java developer, 25% — test automation engineer.
Как видите, не всегда нужны портфолио. В моем случае реальное собеседование было только одно — при переезде в Ригу.
Что касается изучения английского — в Риге в кинотеатрах фильмы идут на языке оригинала, это явилось толчком к прокачке восприятия на слух. Очень много технических курсов смотрю на английском. Мультфильмы с детьми тоже стараемся смотреть на языке оригинала. В Риге курсов по английском никаких не проходил, язык качаю просмотром видео контента и прослушиванием подкастов, а так же общением с коллегами.
Что касается собеседований (и как испытатель, и как испытуемый) — не старайтесь придать себе вес понятиями, в которых плаваете. Вывести на чистую воду очень легко, а вот впечатление о себе подпортите. Лучше честно признаться, что с данным материалом не сталкивался, но при необходимости все подтяну. Перед собеседованием не поленитесь продумать, что вы хотите/собираетесь рассказывать о себе, о своих предыдущих проектах, о своих целях на ближайшие 3-5 лет. На моем первом собеседовании вопрос «кем я себя вижу через 3 года» поставил меня в тупик.
Что касается текущего проекта. Проект построен на Spring технологии. Поддерживается «зоопарк» СУБД, для их контроля используется Liquibase (система контроля и версионинга БД). Очень много интеграций с различными системами. Во все это меня «погрузили» даже без малейшего представления что такое Spring, Hibernate и т.п. Во всем этом приходится разбираться на ходу. Параллельно просматриваю видео туториалы, читая отрывками книги.

P.S.
Эта статья родилась из ответа на один из комментариев к предыдущей success story. Попытавшись начать отвечать, понял, что для комментария уже слишком много.
Не бойтесь ошибаться.

3-4 ноября в Санкт-Петербурге пройдет крупнейшая ежегодная Java-конференция Joker 2017.

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

Вы сможете лично пообщаться с Евгением Борисовым, Барухом Садогурским, Виктором Гамовым, Алексеем Шипилевым и многими другими известными экспертами.

Регистрация уже открыта, можно купить билеты по низкой цене. А если использовать ключевое слово JokerRush при регистрации, цена станет еще ниже!

Подробности и регистрация: goo.gl/QNDDR3

К звездам через тернии

Челябинск. 2015 год. Пятый курс педагогического колледжа, преддипломная практика успешна завершена. Впереди два коротких месяца до… Неизвестности.

Конец лета 2016 года, Питер. Я веду внутренний спор сам с собою. Нет, нужно звонить родителям незамедлительно, такая новость, а они не верили. Но вдруг что-то пойдет не так? Лучше дождаться окончания испытательного срока, и вот тогда. Но целый год безуспешного поиска! Боже, как хочется рассказать всем. Но нельзя.

Сейчас я полон сомнений. Это ли мой путь?

Я помню весну 2015 года солнечной. Знакомые студенты, как впрочем и я сам, бегают в радостном волнении. Немного страшно, но хорошая погода, близость конца пятилетнего обучения пьянят. Все только и разговаривают о дипломе или о том, что дальше. Я возвращаюсь в общежитие, закрываю дверь в комнату. Действительно, а что же дальше? Я — будущий молодой учитель? Возможно во мне всегда было что-то, что говорило нет. Тут и мой цинизм, амбиции, тщеславие, — в общем все то, что хорошему учителю категорически запрещено. Я не пытаюсь оскорбить педагогов, но именно в нашей стране — это одна из тех профессий, от которых, если ты не абсолютный альтруист, нужно спасаться, как с идущего ко дну корабля.

Однажды, еще десятилетним мальчишкой, я зашел домой и — о чудо! — я увидел компьютер. Новенький, шумно жужжащий Pentium 3 или 4? В первый же день я побежал к друзьям за их играми — GTA, Need for Speed, Warcraft III. Теперь, спустя десяток лет с небольшим, я жалею, что мои родители, как вероятно многие родители тех времен, не увидели всех возможностей этого чуда 20 века, компьютеров. Поэтому, пройдя через бесчисленное количество ссор, запретов и обид, я стал всего лишь типичным подростком-геймером. Хотя можно выделить небольшой плюс: в силу того, что мой уже второй компьютер имел всего лишь 256 МБ оперативной памяти (и соответствующее ей остальное железо), мне постоянно приходилось искать способы повысить производительность в играх. Так, например, я научился переустанавливать Windows и прочий нужный софт и даже немного зарабатывал на этом, помогая студентам и знакомым с их компьютерами.

Не знаю, как так вышло, что лишь на последним курсе, перед лицом все нарастающей угрозы «стать никем», я задумался о том, чтобы попробовать себя в программировании. И я все еще иногда спрашиваю себя: почему не раньше? Первые попытки были не совсем удачными: в русском сегменте интернета были (и есть) в большей части лишь половинчатые статьи и примеры программ, которые лишь немного сложнее «Hello, World!», и почти не приносили какой либо практической ценности. Затем, в силу того, что по специальности я «учитель иностранных языков», я попробовал искать информацию на английском языке. Так я нашел потрясающий сервис Khan Academy с их курсом по Java Script, этим сервисом я пользуюсь и сегодня, но изучаю уже другие предметы. Не помню точно, но тогда еще на Khan Academy не было курсов по полноценному Web (либо я их не нашел), поэтому закончив их курс по JS, я оказался в очередном тупике. А затем я открыл для себя Javarush.

Как вероятно у многих, мои первые 10 уровней пролетели быстро. Меня очень удивил и понравился их стиль преподавания (учитель оценил). Оценил я и предприимчивость создателей сервиса — ведь до сих пор у JavaRush нет подобных по стилю и контенту конкурентов. А как, хотя это и очень банально, грели ум и сердце их истории в конце каждого уровня про успех, образование, заграницу! Поэтому, почти не раздумывая, я купил курсы.

Было особенно тяжело, когда я добрался до 15-16 уровней. Работа с потоками, нитями и прочими непонятными вещами, — все это обескураживало. Были моменты, когда я забрасывал учебу, потому что больно. Больно от того, что 20 попыток, а задача не проходит проверку. Явно грешил — копировал решения задач с github, при этом не всегда вдумываясь, что же я копирую. Так я добрался примерно до 25 уровня. На фоне неуверенности в себе, самокопания от того, что я не самый «честный» ученик, во мне зарождалось какое-то еще одно не очень приятное чувство. Что-то не давало мне покоя, пока наконец я не осознал что: я понял, что несмотря на 25+ уровень, я все еще ничего не знаю и не умею толком. Имеется ввиду именно то, что я до сих пор не мог просто сесть и написать что-то действительно важное и полезное. Не видел общую картину того, как строятся большие, мощные приложения. Одно дело решить интересную логическую задачу, и совсем другое — написать игру, мессенджер, свой сайт. Программирую, не умея программировать.
Здесь я принял одно из своих очень важных, но по наивности абсурдных, даже в каком-то смысле глупых, недалеких, решений: Я переезжаю в Питер.

Я переезжаю в Питер не просто так: в Челябинске нет вакансий Java программистов. Москва отпугивала количеством живущих там людей, ценами и всеми теми «байками», которыми любят делиться люди, никогда не жившие ни в одной из столиц. В то же время, Питер казался загадочным, манящим, эдаким застрявшим в 19 веке прибежищем для не нашедших себя романтиков.

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

Приехав, я сразу же записался на JPoint — конференцию для Java разработчиков (в тот раз специально для студентов). Не знаю для чего я пошел туда с моими-то знаниями, но скорее всего инстинктивно, для еще одного хорошего «пунктика» в резюме. Поиски начались в октябре 2015. Свою первую работу я нашел в августе 2016. В октябре и ноябре я был воодушевлен, коленки на первом собеседовании тряслись, а отказы расстраивали не так сильно — все-таки я же еще новичок? Настроение сильно ухудшилось зимой. К весне я нашел «стажировку мечты» в одной хорошей немецкой компании. Провал. Как раз в марте — ровно год покупки курсов на JavaRush. А теперь добавьте сюда еще отсутствие денег, коммуналку, в которой и врагу не пожелаешь жить, отсутствие работы вообще какой бы то ни было, а главное каких либо новых перспектив. И здесь я сдался. Забыл о программировании на 4 месяца. Не мог о нем думать. Малейшая мысль о том, чтобы «покодить», вызывало чувство паники, отвращения и тошноты.

И вот он я — промоутер на главной улице Петербурга. С дипломом учителя иностранных языков, с разбросанными по всему уму знаниями-ошметками про Java, SQL, Spring, Hibernate, HTML, JS, CSS. Да, наши экскурсии на теплоходах лучшие. Yes, we have blankets and english audio guide. Давайте я вас провожу к причалу. Нет, из-за того, что я вас провожу, цена билета не изменится.

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

А затем как всегда, как это часто случается во всех банальных цитатах, в одинаковых как день фильмах и кричащих безвкусицей киосочных книгах — произошло чудо, которого ВОТ ПРЯМО СЕЙЧАС ты не ждал. Только, как в случаях с фильмами, я не влюбился — первая работа программистом нашла меня. В конце июля, начале августа, я решил «просто отправить пару резюме». Обычное тестовое задание, обычное собеседование. Обычное неверие, что мне хотя бы даже ответят. Правда времени дали немного, а с моими 14,5 часов сменами его еще меньше. Кое как успел, отправил и забыл. Потом, в самый обычный день, я зашел на почту и не поверил тому, что прочитал. Прочел еще раз. И еще. И еще.

Первые дни. Я всего боюсь. Какие-то люди, объясняют, что делать, из чего состоят наши сервисы, как все работает. Я киваю, запоминаю ровным счетом ничего. В конце рабочего дня я выжат, сил, как и желания что-то делать, нет. Успел выполнить первое задание за 3 недели (которое сейчас я сделал бы за день). Меня похвалили, сказали, что со следующего месяца я полноценный член команды. Здесь я даю себе волю похвастаться всем, кому хотел все это время, но не мог, так как боялся потерпеть еще одну неудачу. В голосе гордость. Вот, вы не верили, а я смог. Нет, мне не нужен институт, я сам. Не хочу терять время и деньги.
По улице иду улыбаясь, с превосходством и самодовольством поглядывая на «людишек». Не верю, что мне платят столько за то, что я… сижу перед компьютером. Это так странно. С каждым месяцем становится все легче; я уже не выжат как лимон в конце рабочего дня. Повышение. Нашу команду пригласили на хакатон для студентов. Иронично, что я один из менторов и студенты идут ко мне с вопросами. Чувствуешь, как твои знания ширятся, как земля под ногами становится тверже. Но вместе с этим я понимаю, как много еще я не знаю.

Попытки создать с другом свой проект. Первое понимание того, как сложно приложение довести хотя бы просто до работающего прототипа. И дело тут не в сложности. Нехватка времени, усталость от «кодинга» после работы, лень, другие отговорки. Замкнутый круг. Я вспоминаю лектора из той немецкой компании, из которой я с треском вылетел; он с горькой иронией рассуждал про то, как много молодых стартаперов действительно становятся таковыми в реальности, а не просто в своих мыслях.

Сейчас я полон сомнений. Это ли мой путь? Банально, но худа без добра не бывает. Вскоре я начал понимать, что хотя Java — очень мощный язык, возможности которого огромны, — его применение ограниченно. Мне мало, если так можно выразиться, Web Enterprise'a. Да и потом, я называю себя программистом, но действительно ли являюсь им, а самое главное — хочу ли? Скорее всего, это лишь одна из множества мелких остановок на пути к заветной, но едва ли выполнимой мечте — найти настоящего себя. Найти и проявить то, что не зависит от уровня зарплаты, престижности и нужности профессии сегодня.

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