Как так выходит, что проводя по несколько часов каждый день за изучением программирования, складывается ощущение что мы это делаем медленно и топчемся на месте?
Привет, Хабр!
Разрешите представиться, Василий, начинающий .NET разработчик. На столько начинающий, что до сих пор не был приглашен ни на одно собеседование. Это, собственно, и не удивительно – я квалифицированный экономист и последние годы занимал соответствующую должность, а с недавних пор (сентября прошлого года) решил сменить сферу деятельности и изучаю программирование в надежде найти работу в IT индустрии.
Нет, не переживайте, это не будет очередной статьей из серии "успешного успеха", где у меня получилось за считанные месяцы найти себе место на галере под солнцем, и я только успеваю, что отбиваться от назойливых HR, которые хотят уже переманить к себе. Да и не будет драматичной саги о том, что жизнь сурова и не справедлива, я столько трачу сил, а выхлопа ноль, а вот <Любое_Имя> после курсов пустил пыль в глаза, теперь уже почти синьор. В конце концов процесс обучения и трудоустройства как марафон – выигрывает не тот кто может развить самую быструю скорость, а тот кто кто трезво рассчитывает свои силы и способен поддерживать темп на всей дистанции.
История, которой я хотел бы с вами поделиться, и её мораль вообще в другом. И в первую очередь я хотел бы поделиться ей с "попутчиками" – людьми, которые также как и я изучают для себя что-то новое, стремятся в мир ИТ. Если вы тоже испытываете ощущение, что застряли на каком-то месте, или что обучение протекает слишком медленно, возможно вам немного помогут мои соображения.
В последние дни меня не отпускает стойкое ощущение, что мой прогресс в учебе слишком медленный. Поскольку я не учусь по какой-то конкретной программе, у меня нет преподавателя или наставника, как и четкого плана со сроками, то очень сложно объективно оценить свой прогресс. Только субъективно, причем критериев оценки тоже как таковых нет. Чужой опыт тоже ведь не самая объективная оценка для своего пути, ведь кто-то трудолюбивее и умнее, кому-то возможно повезло, кто-то привирает и умалчивает детали. Вот и выходит, что единственный ориентир - собственные первоначальные ожидания и завершенные проекты. В моем случае я думал, что к концу года буду понимать C# на базовом уровне, будет пару pet проектов на гитхабе, в уже наступившем году буду рассылать резюме по компаниям, ходить на собесы параллельно повышая хард-скиллы, решая задачи на литкоде, пополняя гитхаб профиль новыми проектами. Да, наивно конечно сейчас ставить такие сроки самому себе и сокрушаться, что ты их нарушаешь, но хотелось бы все таки разобраться, что же так замедляет учебу?
Причина № 1. Мы переоценили собственный опыт.
Мне немного повезло с бэкграундом. Хоть я имею экономическое образование и последние 7 лет стажа с этим связаны, всю свою осознанную жизнь интересовался технологиями. В детстве я с азартом изучал турбо паскаль и составлял простенькие программы на нем, даже отправляли из-за этого на какие-то районные олимпиады по программированию. Потом стало интересно, что такое сайты и из чего состоят. Так в моей жизни появился PHP 5, который с интересом изучал и опять же, писал какие-то простенькие совсем вещи. Из книги узнал, что есть какие-то CMS которые обычно работают на Linux серверах. Так в моей жизни появился ArchLinux, который несколько лет стоят основной системой, и LAMP. Мне было интересно, что такое маршрутизация и сети, так у меня в библиотека появилась книга по телекоммуникациям, а из нее в голове знания про топологию, адресацию, семиуровневую модель и т.д. Даже системным администратором успел поработать.
К чему всё это я поведал? Что мой опыт в профессиональном программировании нулевой, но при этом нельзя сказать, что в IT полный ноль. Видимо в какой-то момент я решил, что новые знания, которые я планировал получить, отнесутся с уважением к моему опыту и более охотно усвоятся в моем мозгу. Ага, конечно. Не будет никакой поблажки в учебе. Не важно, имели ли Вы какой-то опыт программирования несколько лет назад, работали ли тестировщиком, или составляли программы на лабораторных занятиях. Если речь идет об обучении, нацеленном на трудоустройство и постоянный заработок, то учеба будет даваться очень тяжело, и не думайте, что ваш бэкграунд даст вам фору и позволит в разы быстрее и проще освоить материал.
Причина №2. Мы используем неподходящую литературу.
Вполне возможно, что очень многим этот пункт покажется немного спорным, но мне кажется, что его стоит осветить. В .NET среде просто огромное количество обучающих источников – руководство от майкрософт, книги от них же, книги от признанных авторов, огромное количество видеоматериалов на Ютубе – всего и не перечесть. Когда я только начинал учебу и составлял список книг, которые я бы хотел использовать для учебы, я столкнулся с проблемой, что на самом деле сложно сделать выбор в пользу чего-то. Во-первых, все очень субъективно, кому-то надо разжёвывать все построчно и в деталях, кому-то достаточно и выжимки. Есть конечно книги бестселлеры, но большая часть из них написаны так давно, что страшно их брать в руки. А если мы всё-таки начали что-то читать, и нам это дается сложно и не понятно, или книга в итоге не впечатляет, то мы скорее смиримся с тем, что с нами что-то не так, нежели с книгой (да, синдром самозванца и про него будет чуть ниже).
Мой личный пример – это книга A. Freeman «Pro ASP.NET Core 6». Солидное издание, девятое по счету, последняя версия SDK рассматривается (на тот момент 6.0), много положительных отзывов в интернете, подробные листинги – то, что нужно, решил я, когда начал изучать ASP.NET Core. Потратив почти месяц и прочитав чуть меньше половины, я понял, что просто в пустую потратил это время. В книге вы шаг за шагом вместе с автором пройдетесь по главным шагам и соберете рабочее приложение автора на своем компьютере. Даже с тестами. Но вот эта манера подачи из разряда «скопируйте/вставьте этот код» чтобы реализовать что-то в сухом остатке не дает вам ровно никаких знаний. После прочтения первых 10 глав я понял, что вообще не понимаю даже базового принципа работы фреймворка. Да, мы уже имеем какой-то прототип магазинчика, покрытый тестами, но я книгу начинал читать, чтобы понять, как работает технология. С таким же успехом можно было на Ютуб сходить и найти видео, где за 2-3 часа делают что-то наподобие. Тот же А. Lock в своей книги первые 10 глав разжёвывает базу – что такое эндпоинты, что такое контекст, что такое pipeline и как через все это дело проходят запросы/ответы. Все понятно стало сразу же. Если Вы ощущаете, что обучение дается вам очень трудно, возможно Вам стоит рассмотреть другие источники и сменить книгу, посмотреть другие лекции и т.д.? И да, ни в коем случае не читайте книги в переводе, в 9 из 10 случаев это очень больно и только усложняет процесс. Вроде и слова все знакомые, и язык родной, а смысла в них нет. И когда ты подсматриваешь в оригинал, о чудо! – смысл появился, они и был и предельно понятен изначально. Просто не понятен переводчикам, они все-таки не разработчики, поэтому даже лучше приложить чуть больше усилий и читать в оригинале, переводя самому непонятные моменты, чем гадать над идеями автора в исполнении переводчика.
Причина №3. Утопия чистого кода.
Ни в коем разе не хочу утверждать, что идеи Роберта Мартина утопичны, или что вам в учебе не стоит равняться на лучшие практики. Действительно надо стремиться к оптимизированному коду, легко читаемому и понятному. Но вот дилемма, как быть в ситуации, если вы ограничены по времени? В своих первоначальных планах я думал, что буду стараться писать сразу вменяемый код, но без фанатизма, естественно с оговоркой, насколько это вообще возможно начинающему разработчику, чтобы в дальнейшем его шаг за шагом улучшать. Р. Мартин утверждает, что
«Самая большая ложь, в которую верят многие разработчики, — что грязный код поможет им быстро выйти на рынок, но в действительности он затормозит их движение в долгосрочной перспективе»
Спроецировав его утверждение на свой опыт, я решил – окей, будем прикладывать максимум усилий для написания сразу максимально возможного качественного кода, ведь звучит логично и правдоподобно. Мы ориентируемся на открытые вакансии, где каждая вторая компания хочет от кандидата понимание SOLID, использование принципов DRY, KISS, YAGNI и вообще, по-хорошему надо работать по TDD, а еще знать, понимать и применять паттерны проектирования. Оставим за скобками как на самом деле пишут код в некоторых таких компаниях и как они соблюдают все эти принципы сами. В итоге мы, начинающие, равняемся на эти требования, хотим от себя большего, нежели можем на текущий момент, тем самым замедляя свой прогресс. Да, возможно в долгосрочной перспективе такой подход даст свои плоды, мы будем знакомы с лучшими практиками, но вот вопрос, на который у меня нет до сих пор ответа. Что же на самом деле важнее и лучше, тратить много времени на «причесывание» своего pet проекта, либо за это время изучить еще какую-то технологию и сделать два проекта, пусть и не таких идеальных с точки зрения кодовой базы. В итоге, в моем случае, именно из-за этого желания «сделать по уму», я существенно отстаю в развитии от первоначальных сроков, имею лишь один проект на гитхабе, который, мягко говоря, далек от совершенства.
Причина 4. Мы недооцениваем свои возможности. Всем знаком «синдром самозванца», я много раз про него слышал и был уверен, что это больше относится к людям, которые оказались в окружении специалистов и на их фоне чувствуют себя не уверенно. И обычно это приходит как раз уже после трудоустройства в какую-то компанию. Я был уверен, что меня это не коснется, да и до трудоустройства еще надо дойти, но каково было мое удивление, когда я понял, что уже испытываю нечто подобное уже сейчас. Казалось бы, с чего бы это? А все просто, даже когда вы учитесь, вы уже находитесь в окружении специалистов – вы видите ответы на stackoverflow, открытые issue на гитхабе, всевозможные тематические статьи и мало-помалу у вас формируется убеждение, что вот они – вот да, специалисты, а вы так, даже не джун. И в итоге вы начинаете тратить еще больше времени, чтобы перепроверить свои выводы, убедиться правильно ли вы поняли какой-то подход и верно его реализовали, вы постоянно сомневаетесь в собственных решениях и регулярно ищете им подтверждение. А уж если у вас какая-то ошибка, то значит это вы что-то сделали не так и вы будете тратить еще больше времени на поиск ее причины, даже не допуская мысль, что возможно это просто баг окружения или фреймворка, а не ваша вина.
У меня за столь короткий период обучения было два таких случая. Первый был связан с реализацией IHttpClientFactroy. Простая задача – отправка get запросов через прокси и обработка json в ответе. Можно создать просто экземпляр HttpClient, ему передать при создании собственный хэндлер, который будет содержать информацию о прокси. Все супер просто. А как быть, если нужно в один момент отсылать 10 запросов и все с разных IP? Для таких вещей отлична подойдет фабрика, так утверждала и документация, и стэковерфлоу, огромное количество статей в интернете. Я это реализовал, но в итоге это не заработало. У меня ушло несколько дней, чтобы, перелопатив кучу информации в сети, подтвердить свою гипотезу, что в моем конкретном случае фабрика не будет работать так, как мне нужно и придется в итоге обойтись без нее. Как говорится, это не баг, а фича – сколько бы хэндлеров вы не создали, как бы вы их не регистрировали, из какого бы экземпляра не вызывали, пока не истечет SetHandlerLifetime – фабрика будет использовать один и тот же хэндлер, а в моем случае все запросы пойдут с одного и того же IP, что сводит на нет весь смысл реализации этого интерфейса.
Второй случай, который разрешился буквально вчера. Тот же проект, работа с БД через EF Core. Дошли руки до реализации сидинга, да вот какая незадача, при попытке добавить диапазон записей и его сохранить вылетает Exception:
System.InvalidOperationException
Unhandled exception. System.InvalidOperationException: The property 'Player.Id' has a temporary value while attempting to change the entity's state to 'Unchanged'. Either set a permanent value explicitly, or ensure that the database is configured to generate values for this property.
Ну это уже точно моя криворукость, значит где-то накосячил – с разметкой таблицы, с атрибутами и т.д., раз по одному объекту сохраняется нормально, а при диапазоне – ошибка. Несколько дней перебирал все возможные варианты, добавлял-удалял базу, переделывал схему, менял атрибуты – все без толку. После прошлого случая я задумался, а может быть все-таки баг и не мой косяк? К этому подталкивал тот факт, что, не смотря на исключение, данные в таблицу таки сохранялись, а сама ошибка и ее природа намекают на причины, не от меня зависящие? И как только я допустил мысль, что это баг фреймворка, а не мой косяк, решение нашлось за 15 минут. Как говорится, главное знать, что спросить. Нашелся аналогичный случай на гитхабе(отдельная история о том, сколько времени и сил стоило его автору подтвердить наличие этого бага – тут конечно только мое почтение и уважение таким людям), который в январе с обновлением на версию 7.0.2 пофиксили и закрыли. В этот раз точно не фича, а баг.
Иногда все-таки так бывает, что, если что-то не работает так как вы планировали, это не всегда означает вашу ошибку. Да, чаще всего это именно так, но не стоит так сильно сомневаться в себе и своем коде, чтобы отрицать возможность ошибки не по вашей вине.
Причина №5. Мы пытаемся объять необъятное.
В самом начале своего пути я руководствовался простой логикой, что сперва стоит изучить основу – язык программирования, в моем случае C#. А дальше уже, в зависимости от дальнейших планов браться за фреймворки и постепенно изучать детали. На практике все гораздо сложнее, ведь для того, чтобы понять, как что-то работает, вникнуть и усвоить, приходится сворачивать с дорожки в строну других технологий, что естественно занимает время и вы это изначально не могли предвидеть. Опять же, из небольшого личного опыта на пути Backend разработчика. За что браться после базового освоения языка? Логично, что за Entity Framework – одну из самых популярных ORM по работе с БД. Но вообще, неплохо бы начать с базы – T-SQL. Окей, тратим на него немного времени. Изучаю Д. Смита «Entity Framework Core в действии» и ловлю себя на мысли, что вообще не понимаю, о чем речь. Почему? Да потому, что уже в первой части идет речь про абсолютно незнакомые контроллеры и как это работает в Web приложениях. Я уже молчу про какие-то слои приложения, и непонятные абстракции. Окей, делаем очередную паузу и изучаем ASP.Net Core, а это, знаете ли, отдельная большая тема. Да и не сказать, что там все просто и понятно. К тому же, всё почему-то реализовано через какие-то интерфейсы. Окей, делаем паузу внутри паузы и идем изучать что такое DI, попутно читая Д. Скита «C# in Depth», чтобы лучше понять, как работает LINQ, асинхронные вызовы и что такое расширяющие методы. В итоге ушел не один месяц, чтобы все это стало понятным. Собственно, это и есть цель обучения, осваивать новые технологии и принципы, но оглянувшись назад понимаешь, насколько сильно мы просрочили время. Поэтому возможно стоит признать тот факт, что перед нами стоит огромная и сложная задача, для решения которой требуется приложить немало усилий и времени, и, возможно, мы несколько ошиблись в своих первоначальных временных просчетах.
Вывод. Не стоить хотеть от себя слишком много, особенно если это для Вас сложная задача. Вода камень точит, как говорится, поэтому стоит продолжать методично, шаг за шагом черпать новые знания, регулярно практиковаться в написании кода и поменьше смотреть по сторонам. Не обращайте внимания на все эти успехи вокруг – вы никогда не узнаете правды, что за всем этим стоит на самом деле. Идите своим путем и при должном терпении и упорстве все получится. Да, возможно чуть позже, чем вы того сами хотели, но всё же главное результат, а не срок.