В 2024-м разработчики, использующие AI, выглядят подозрительно: ты настоящий айтишник или только промпты писать умеешь? Но к 2035-му ситуация полностью поменялась. Многие разработчики в ГПБ умеют писать только промпты, но при этом они — настоящие айтишники.
Довольно интересный вопрос каким образом менялся образ "настоящего айтишника" в профессиональных кругах с течением времени (в большей его части). Раньше такого понятия вообще не было, оно появилось (по большей части из-за СМИ) сравнительно недавно. И в разных социальных кругах, в разных профессиональных сообществах это понятие может быть сформулировано вообще по разному.
На этот образ также влияет и прогресс в разработке инструментов разработчика, языков программирования, компиляторов, IDE, различных утилит и пакетов. Сейчас реализовать авторизацию по JWT, организовать связь между клиентом и сервером по WebSocket'ам, написать свой сервер REST API или даже сделать свою игру стало проще простого. Раньше приходилось больше изучать и больше практиковаться, чем сейчас.
Титанических усилий стоило разработать Nginx, Unity, Unreal Engine, Node.js, Laravel, Django, Visual Studio (Code || Community), Intellij IDEA, PyCharm, Android Studio и др. Это одни из немногих технологий, которые позволяют нам видеть сегодняшний мир "айти" таким, какой он есть. И эти технологии создали люди, без участия ИИ ассистентов или помощников. Другой вопрос - за счёт чего были созданы эти разработки? За счёт большого числа времени, проведённого за изучением работы сетей, низкоуровневого / высокоуровневого программирования, изучения различных операционных систем и их архитектур. За счёт большого числа потраченного времени на разработку, отладку и тестирование разработок. За счёт определённого бюджета, потраченного на разработку и ещё за многое другое.
Современному бизнесу выгодно вкладываться в проекты, которые можно сделать быстро, также быстро запустить, протестировать гипотезу и начать как можно быстрее продавать свой продукт. Редко кто делает что-то качественно и на совесть, большая часть этого рынка "разгоняется", тем более теперь, когда появились большие языковые модели, различные AI-сервисы и многое другое. Это позволяет делать что-то "на скорую руку" не вдаваясь в детали реализации тех или иных функций и в дальнейшем пользоваться правилом "работает - не трогай".
Бизнес в IT сфере имеет большое влияние. И именно он может определять что вкладывается в понятие "настоящий айтишник" здесь и сейчас. Он может решить, что написание промптов это и есть настоящее "айти", а те кто "умеет профессионально писать промпты к ИИ, хорошо и грамотно формулирует технический текст" явно обладает классными и профессиональными навыками в IT чтобы считаться "настоящим айтишником". Бизнес может сделать из опытных низкоуровневых программистов на Assembler или Си "профессиональных промпт-инженеров для языка Assembler и Си, работающих с ChatGPT", потому что он может платить вторым гораздо больше, чем первым.
Бизнес может "пропагандировать", продвигать и развивать свои идеи об образе "настоящего айтишника" в массы и никто не сможет этому помешать, потому что помогать бизнесу будут такие же "настоящие айтишники". Бизнес может превратить в "луддитов" тех специалистов, которым просто нравится их работа, нравится писать программный код и они кайфуют от этого. Потому что такие "луддиты" бизнесу не выгодны. Они не будут использовать ChatGPT или другие AI-сервисы чтобы добиться максимально быстрого результата. Они не будут по картинкам AI "двигать квадратики, перетягивать стрелочки". Они не будут всю смысловую нагрузку о задаче делегировать на AI, чтобы он решал куда нужно кликнуть мышкой, что там написать и что сделать, чтобы добиться такого то результата. Потому что "луддиты" (в современном понимании бизнеса) - это и есть "настоящие айтишники".
Они сами пишут программный код, сами проектируют и выстраивают программную архитектуру, сами думают над своими задачами и сами же их решают. Сами организуют своё рабочее место, своё рабочее пространство и свой рабочий день со своими задачами. Они не против AI, но и не за то, чтобы полностью в свой рабочий процесс его встраивать. Их максимум - использование AI как умный справочник. Это реальные профессионалы, которых к 2035-ому году будут единицы, поскольку понятие "настоящий айтишник" будет изувечено до основания, а "луддиты" будут фигурировать в различных карикатурах, анекдотах и статьях по типу "Луддит не смог запрограммировать игру за 24 часа, в то время как XXXGPT сделал это за 1 минуту!".
Когда ты делегируешь всю смысловую нагрузку на AI (а, я уверен, к 2035-ому году всё именно так и будет, с учётом тенденции развития идей "бросайте код, пишите промпт!"), то ты лишаешь свой мозг возможности развиться. В каком-то смысле человек, который сам ничего не разрабатывает, не решает, а делегирует всё это AI тренирует его, а не себя. Себя такой человек никак не развивает, только если в "написании грамотных и профессиональных промптах". И можно сколь угодно говорить "ну те же написал текст, значит ты подумал, пофантазировал, придумал и просто сказал LLM что ей надо делать, значит ты вырос над собой" - это всё равно будут пустые слова, которые имеют мало общего с настоящим положением дел (хотя бы с той же нейробиологией). Решение задач программных / математических / физических / научных и литературных имеют довольно много различий. Одно дело написать с 0 аналог Nginx'а на C++, а другое написать фантастику, которая бы заинтересовала людей, но которая имеет много различий с реальностью (в том числе с абстрактными структурами, которые люди в нашем мире используют для улучшения своей жизни).
Можно даже ввести понятие "современный ИТ-луддит", потому что очень часто я вижу как люди в комментариях, в статьях по теме типа "ИИ заменит программистов" пишут, что-то вроде "все кто против прогресса - луддиты" или "всех заменят, а те, кто не хочет заменятся или меняться - луддит".
Современный ИТ-луддит (warning: в это понятие я вкладываю свой смысл и не навязываю его никому) - это человек, который хочет, может и будет думать, рассуждать и решать задачи с помощью своего мозга и заложенного в него интеллекта, а главное - ему это нравится. У данного человека есть и будет своё мнение, которое сформировано в результате приобретения им определённого опыта и навыков, а не встроено в его мозг с помощью "ИТ-курсов от передовых бизнес-компаний". Его знания приобретены в результате практики и прочитанной технической литературы, а не просто необдуманной копипасты с интернета или с ChatGPT. ИТ-луддит уважительно относится к своему интеллекту и поддерживает его в тонусе.
Я ни в коем случае не хотел очернить как-нибудь бизнес или AI, мне самому нравится изучать Machine Learning, архитектуру GPT и разрабатывать модели на Python, да я даже учусь по этому направлению и планирую через год работать в этой сфере или смежной с ней. Просто я считаю, что забывать о том, кто такой "настоящий айтишник" не стоит. У каждого это понимание своё, но транслироваться в массы будет наиболее выгодное для текущего времени, что может огорчать и выводить на эмоции и об этом не стоит забывать.
Проведу низкоуровневые оптимизации. Все это стало возможно благодаря развитию ИИ.
Не совсем понял что Вы тут имели ввиду. Низкоуровневая оптимизация критически важных или просто важных функций используемых в JavaScript были и есть возможны без развития ИИ. Достаточно, например, по изучать открытый код популярного для JavaScript движка V8 - https://github.com/v8/v8. Он, правда, написан по большей части на C++, но всё равно там есть за что ухватиться. Например, выбор и реализация стратегии сборки мусора на JavaScript. Есть ведь куча стратегий (итерационная, по поколениям, "в свободное время") и как-то это нужно всё оптимизировать. У каждого JavaScript движка есть свои внутренние механизмы для этого и они написаны именно с целью оптимизации и увеличения скорости выполнения JavaScript кода. Или хороший пример Node.js (https://github.com/nodejs/node) там вообще сплошь и рядом использование C/C++ модулей в JavaScript (на базе Node.js). Это всё было возможно задолго до развития ИИ.
Например, в бенчмарке
В каком именно? Не совсем ясно откуда появились в статье "очки" и каким образом они считаются. Не понятно вообще как в статье пришли от темы ускорения JS до оценки по каким-то очкам популярных JavaScript-фреймворков.
Разработчик среднего уровня на JavaScript может написать код, который будет лишь в 2-3 раза медленнее C (что очень даже хорошо)
А есть какая-то статистика? Просто чтобы такое утверждать, нужно либо в буквальном смысле глазами наблюдать большое число таких прецедентов, либо опираться на какое-либо исследование. Упоминания ни о том, ни о другом в статье нет.
с помощью магии оптимизации на низкоуровневом C можно достичь значительного ускорения, на которое компиляторы JavaScript не способны
Не стоит оценивать по скорости компилируемые и интерпретируемые языки программирования, т.к. это две совершенно разные категории и у компиляторов и интерпретаторов стоят разные задачи и возможности вообще, исходя из определённых архитектурных ограничений. Например, движки JavaScript (в большинстве случаев) реализуют Event Loop, который "делает этот язык" (на уровне пользователя) более медленным, чем тот же C, потому что поочерёдное выполнение макро- и микро- задач не может не накладывать отпечаток на скорость. Можно предположить, что если реализуют компилятор для JavaScript, который схож по возможностям с каким-нибудь компилятором С/C++, то скорость будет +/- одинаковой (естественно урезав некоторый функционал из JavaScript по типу EventLoop). Тогда это уже будет не JavaScript, а компилируемый CJavaScript и он будет походить на Go.
Общее впечатление таково, что не низкоуровневые оптимизации стали возможны благодаря развитию ИИ, а эта статья, т.к. есть много вопросов относительно её качества.
Обычно секреты своего успеха не раскрывают... теперь автор этой статьи может воспользоваться Вашей наводкой и у Вас появится новый конкурент в его лице, опасно :)
Тоже уже достали. Сделана как статья, хотя механизм постов уже есть и можно при желании на пост и поменять, хотя смысловая нагрузка там будет точно такой же - нулевой, но вот пожаловаться "какие авторы с телеграм-каналами плохие" - хоть каждый день.
Что плохого в публикации в своём труде ссылок на свои социальные сети / каланы и прочее? Что плохого? Почему это "рак"? И почему это можно оправдать "годными корпоративными авторами"?
Абсолютно не справедливо агрессивно реагировать на то, что авторы публикуют на хабре ссылки на свои телеграм каналы. Это проблема не авторов, а вас самих. Что-то, видимо, тригерит у пользователей, когда они читают "подписывайтесь ...".
В какое время мы живём? Во время, когда продвижение решает многое. Уже давно пора привыкнуть к тому, что на публичных ресурсах люди будут продвигаться и для этого нужно в своих материалах оставлять ссылки на себя.
Даже при написании научных статей люди оставляют ссылки на работы, которыми пользовались - библиографический список называется. Возможно между библиографическим списком в научных статьях и сегодняшним "трендом на продвижение" можно составить корреляцию, полагаю что она тут есть, в некотором эволюционном или переносном смысле.
Любой человек, пишущий на хабре, так или иначе продвигается. И ничего Вы с этим сделать не можете (как бы не хотели). Ни Вы, ни кто либо ещё. Даже без оставления ссылок на телеграм-каналы идёт продвижение. Так, а смысл тогда быть противником продвижения? Вы не находите это смешным? Мы все здесь о себе в той или иной мере заявляем. Заявляем что мы можем написать техническую статью, что мы разбираемся в интересующей нас теме (или не очень), что мы можем и делаем. Люди пишут статью для разных целей.
Могу подкинуть новую идею для "мнения" - "Рак, убивающий Хабр, ака "написание технической статьи"", потому что любая техническая статья - это продвижение.
Автор ссылки на себя оставил в самом конце статьи, содержание статьи хорошее, но дизлайки она получила не заслужено. Просто потому что "телеграм канал, ааа, триггерит".
Желаю всем встречаться с триггерами только когда пишете SQL-код для работы с базой данных, а статьи и "мнения" оценивать объективно.
Я тут с Вами не соглашусь. Не то, чтобы я "профессионал" в написании статей, но кое-какой опыт всё же имею и Ваше утверждение "мусор на тематическом ресурсе" мне напомнило о недавней статье, которая Вашему утверждению полностью соответствует, но при этом это одна из самых "залайканных" статей, которые я на этом ресурсе видел:
Уже судя по названию можно сделать вывод, что статья "мусорная" и не несёт какую-то пользу обществу, вообще никакой, при этом оставаясь в нашем домене (ИТ). А прочитав эту статью можно вообще сделать вывод, что это пост. Анегдот ещё в том, что этот "мусорный пост" (я не знаю как его иначе назвать) является переводом! В этом посте человек просто жалуется на то, что он "тупой" используя при этом "крутые технические термины" типа "распределённый кэш", "микросервисы" и другое.
Здесь автор хотя бы старался написать добротную статью, подумал над оформлением, даже задел тему с ИТ связанную (как ни крути, но популярность no-code растёт и я лично знаю группу разработчиков, которые используют Bubble для решения своих задач и используют его успешно), а в одной из самых "залайканных" статей этого нет. Ни хорошего оформления, ни интересной истории (а история рассказанная в статье действительно интересна), ничего.
И ссылка на телеграм канал даётся в самом конце статьи и никак не обязывает Вас или других на автора подписываться и никаких "неэтичных" поступков автор не совершил, но комментарии с этим "замечанием" получают всё же плюсы. Это какой-то сюр.
Я не завидую "мусорному посту" с большим числом лайков, я просто призываю читателей быть объективными при выставлении минусов таким статьям. Авторам нужно давать второй шанс или вообще их не читать, если отдельные индивидуумы вам не интересны.
Но эта статья вообще не обосновано получила -33. Может технических деталей тут нет, но согласитесь, это гораздо лучше сделанная работа чем "мусорный пост", ссылка на который представлена выше?
И ничего нет такого, что люди дают ссылку на свои контакты - все тут для продвижения, самовыражения и прочих целей связанных с личными интересами (кроме комментаторов, которые пишут мусор и не сделали ни одной статьи, но других "поругать" - хлебом не корми).
Товарищи, будьте объективны, только благодаря вашей оценки "мусорные посты" продвигаются вверх или вниз. Этот пост к этому числу не относится (см. пост выше).
погружение (честно не знал, что в синтетических ивентах нельзя его перехватывать)
Перехватить синтетическое событие на этапе погружения можно. Это делается с помощью добавления постфикса Capture в атрибут обработчика какого-либо события в JSX.
Например, следующий код перехватывает событие клика на этапе погружения и всплытия:
Вообще, можно разделить критику на две группы (так проще): токсичная и здоровая.
Токсичная критика в целом не несёт ничего хорошего как для автора статьи, как для самой статьи, так и для автора токсичного комментария изложенного выше.
Напротив же здоровая критика способна направить автора на продолжение исследования темы, может расширить его кругозор, она помогает дополнить рассматриваемую тему, улучшить саму статью.
Я считаю, что Ваша критика не совсем здорова. Ваши высмеивания издержек из моего труда (которые, к слову, ошибочны) это демонстрируют.
Обругать можно что угодно и быть токсичным проще простого. Вообще как "нефиг делать". Вы попробуйте быть терпеливым, сдержанным, уметь направить других людей в нужном направлении. Это сложнее всего. И к этому, я считаю, нужно стремиться.
Теперь к самому комментарию.
Изобретена какая-то своя терминология: Обработчики событий почему-то называются событиями
Я ничего нового не изобрёл. Укажите где Вы увидели путаницу между событиями и обработчиками событий? Признаюсь, я проверял статью несколько раз и не увидел, чтобы где-то было это нарушено, потому что если столько раз писать о событиях и иметь определённый эмпирический опыт в их написании, то невольно можно ошибиться. Я разделял в статье события и их обработку. Укажите пожалуйста место, где я этого не сделал - поправлю.
Синтетические события - это круто и лучше чем нативные потому что синтетические нас защищают от утечки памяти. Классный довод, хорошо бы ещё раскрыть, а то мантра какая-то (читателю поразмышлять?)
Где я написал, что синтетические события это "круто" и что они "лучше" нативных? Вообще не к этой статье относится. Может прочитали что-то одно, потом пришли почитать эту статью и у Вас всё смешалось? Такое бывает, это нормально. Я указал на чёткую разницу между синтетическими и нативными событиями. И то, что для решения описанной мной проблемы пользователь может захотеть переписать функциональные компоненты на классовые - это просто факт. Ну нет охоты у читателя переподписку делать, проще классовые компоненты сделать. Этот пункт Вы просто сами придумали (кроме утечки памяти, это в статье действительно было).
Браузерному Event отказывают в праве называться нативным потому что там могут быть другие свойства не из спецификации (а обоснование этого "предлагаю читателю поразмышлять"). Что за своя терминология? Нативность и спецификация вообще разные свойства. Как цвет и вкус
Где я отказывал в праве браузерному событию называться нативным? Я просто высказал своё мнение. Внимание, это было моё мнение, а не навязывание какой-то позиции. Я никакой позиции своей тут не навязываю. Спецификация это одно, а реализация этой спецификации под разные браузеры - это другое. Именно это я и отразил в своём скромном мнении о нативных событиях.
Нативность - не мой термин. Он существует с тех пор, как люди стали разграничивать высокоуровневые вещи и низкоуровневые в контексте программной (и не только) реализации.
вот смотрите этот код работает хорошо, потому что он синтетический. А этот не работает, потому что он не синтетический. Довод офигенный. Оказывается дело не в том что автор написал код с тривиальным багом который линтер с плагином для react не пропустит.
Опять придуманный пункт. Я поясняю почему он обработчик нативного события не работает, а синтетического - работает. Почитайте комментарии выше, может это Вам что-то даст в понимании (в том числе мои цитаты к статье).
Кстати, если Вы называете эту особенность "тривиальным багом", то Вам стоит лучше разобраться с этой механикой, потому что это не баг и он не тривиальный.
"Внимательный читатель..." + "Обработчики нативных событий не захватывают состояния, но захватывают refs". Вау блин. А "Синтетические" (в терминологии автора конечно) захватывают что ли? Оба варианта замыканий работают одинаково (это javascript всё таки, автор понимает как он работает?) Нативный обработчик автор значит замемоизировал с багом (тем который видит eslint) указав неверные dependencies, а синтетический обработчик он бодро пересоздает каждую перерисовку и радуется
Речи о замыканиях тут вообще не шло. Речь шла о захвате контекста компонента. Не более. На счёт "мемоизации с багом" - ну, как свой eslint настроите, так он и будет работать. У меня всё работает так, как я и ожидаю. Рекомендую ознакомиться с темой мемоизации и кэширования в React.js (+ чистые функции), может быть Вы к такому коду отнесётесь более сдержанно, потому что в массив зависимостей useEffect'а добавлять обёрнутую в useCallback функцию можно, иначе ничего бы не работало :).
Это какая-то вредная статья. Прочтёт её джун, пойдёт на собеседование и начнёт такую же чушь нести наивно :(
Не согласен с Вами. Одна из целей статьи - "повышение осведомлённости" о такой проблеме. В своё время я часто забывал об этой проблеме и совершал ошибки. Если бы где-то было понятное описание этой проблемы и способу её решения - я был бы рад. Не нашёл таких статей - написал сам. Теперь любой желающий может найти эту статью в поисковике и ознакомиться с проблемой, её решением и исключениях. Может быть, даже получит мотивацию для дальнейшего исследования этого вопроса.
Вы если нашли ошибку в статье - напишите критику с указанием ошибки и пояснениями (если Вам есть что рассказать), а не с неаргументированным высмеиванием перекрученных издержек из статьи. От этого и Вам будет польза (потому что Вы лучше разберётесь в этом вопросе) и содержимому статьи (потому что результат здоровой критики не внести в статью было бы небрежно) и лично мне (т.к. я тоже как и Вы разберусь в этом вопросе лучше).
Если уж совсем не поняли - спросите в комментариях, уточните что автор имел ввиду в конечном счёте. А то есть риск формирования у Вас выводов, которые максимально бесполезны и вредны. И Вам и людям, которые их прочитают.
Например, в комментарии ниже автор указал на другой аспект этой проблемы - память. Мне захотелось внести это в статью, что я с удовольствием сделаю, чтобы у читателя было больше возможностей разобраться с этой темой.
А Ваш комментарий в текущем виде... ну, не знаю, пользы от него нет.
Ругать можно что угодно, сложно найти в чём угодно хорошее, как и положительно влиять на авторов статей, чтобы они писали их лучше :)
С первым утверждением частично согласен. Конкретно события - ни при чём. Тут причастны обработчики данных событий, о чём, собственно, и написано в статье.
Ранее я упомянул, что обработчики синтетических событий обязательно должны находиться в определении DOM-элементов (в JSX-коде). И именно благодаря тому, что они определены в JSX-коде "синтетический" код работает правильно, а "нативный" нет. Поскольку обработчики синтетических событий захватывают контекст компонента полностью, а обработчики нативные - нет (лишь частично).
В целом то, что Вы описали (проблема с функциональным компонентом) есть в статье, только я оперирую введённым понятием "контекст React-компонента" и не упомянул ничего про память, думаю это хорошее дополнение. Суть проблемы не меняется - обработчики синтетических событий находятся в JSX-коде и при перерисовке они захватывают все актуальные состояния, а при обработке нативных событий этого не происходит и внутри обработчиков мы всегда имеем начальное значение состояния. Да и не всегда оно начальное. Если использовать hot reload, то можно добиться такого поведения, что в примере из статьи значение currentValue установится на какое-нибудь рандомное единожды, но не более.
Я использовал термин "контекст React-компонента" потому что обработчики событий всё-таки захватывают, например, refs. Поэтому нельзя сказать что вообще все ссылки в этом обработчике не захватываются. Захватываются, только ссылки refs. Ну и ещё можно дополнить этот список "исключений" по мере необходимости.
Ну, а сам "не захват" части контекста компонента происходит как раз из-за того, что Вы описали - ссылки на функцию не теряются, а новые уже не добавляются в обработчик нативного события. Отсюда и есть необходимость переподписки.
По-видимому в классовых компонентах этот пример работает потому что ссылка на функцию обработчик постоянно меняется и нет даже необходимости делать переподписку на обработку нативного события.
Какие события можно считать синтетическими? В общем-то все, которые поддерживаются на данный момент и их обработчики содержатся (важно) в определении DOM-дерева функционального или классового компонента (в JSX-коде).
В статье показана разница между синтетическими и нативными событиями. При описании проблемы я указываю на то, что обработка синтетических событий определена в JSX-коде и все эти обработчики захватывают актуальный полный контекст компонента (внутри них актуальные ссылки на состояния).
Пример с useEffect без массива зависимостей тут не очень подходит, т.к. переподписка на события будет при вообще любом рендере (необязательно при изменении стейта value). В общем-то можно использовать в массиве зависимостей и просто стейт value:
// ...
useEffect(() => {
// Подписка на обработку нативного события
container.current.addEventListener("click", clickHandler);
return () => {
// Отписка на обработку нативного события
container.current.removeEventListener("click", clickHandler);
}
}, [value]);
// ...
Это даст точно такой же эффект, но я написал программный код таким образом, каким посчитал более правильным - через мемоизацию. Сразу понятно что мы кэшируем обработчик, кэш может меняться и если он поменялся - делаем переподписку.
Это класс, который переопределяет стили для конкретного компонента в конкретном месте, вместо стилизации его глобально для всего приложения. Например, через тему.
Есть проекты, в которых используется подход с изолированными css-стилями (так называемый css-modules). При таком подходе имена стилей генерируются автоматически и при подключении их к проекту не возникает никаких конфликтов (если вдруг однажды не будет сгенерировано имя стиля, который уже встречается в проекте... но, это маловероятно). Считать ли такие стили "костылями", только потому, что они позволяют локально переопределять внешний вид элементов? Очень сомневаюсь. Я бы предложил исправить название этого понятия на "локальный стиль", чтобы не вводить в заблуждение читателей, которые только знакомятся с frontend разработкой.
При использовании готовых решений (библиотек компонентов, например) часто приходится переопределять стили стандартных компонент для того, чтобы они соответствовали дизайну (и это нормально). И да, без className тут не обойтись, если нужна какая-то "сложная" визуализация. Библиотеки UI-компонент предоставляют только "базовый" набор часто используемых компонент, но если нужно добавить свои изменения - тут без инструментов для кастомизации не обойтись. Это именно инструмент кастомизации, а не "баг" или "фича". Можно это даже считать своеобразным компонентным API (думаю, что так даже более корректно).
Я считаю, что если проекту не хватает возможностей UI-библиотеки, то стоит либо свою библиотеку разрабатывать (с нуля), либо создавать свои компоненты на основе уже готовых с переопределением стилей через classNames, и лучше это делать именно с помощью сравнительно безопасного подхода css-modules (или styled-components). И это не должно считаться "костылём". Готовые решения не панацея, в любой момент может потребоваться изменить поведение уже готового компонента, это только вопрос времени.
Поток можно интерпретировать по-разному, с учётом обстоятельств, контекста или каких-нибудь общепринятых норм и правил. В программировании поток - это одно, в каких-либо организационных вещах - другое.
В моей статье поток был рассмотрен с точки зрения "течения". То есть фактически можно сравнить поток с потоком реки. А поток реки может ассоциироваться с какими-то постоянными или циклическими процессами. В данном случае поток - это циклический процесс.
Таким образом поток в статье - это какой-либо циклический процесс, в данном случае - анализ и документирование проекта, в котором некоторые элементы повторяются раз за разом (например, комментирование файлов исходного кода или процесс добавления новых API в Swagger UI).
В своей статье я не даю советы об использовании той или иной технологии - это индивидуальный выбор каждого конкретного разработчика и каждой конкретной команды, и выбор этот зависит от многих факторов.
REST API можно реализовать на чём угодно: Gin, Nest.js, Node.js, Django, Laravel, Flask, Spring Boot и так далее - всё зависит от тех самых "многих факторов", на которые я ссылаюсь выше. И документирование API сервиса (или приложения) можно разными способами. Можно действительно писать громоздкие комментарии, точно следуя стандарту Open API, проверяя при этом каждую модель и за счёт этого увеличивать размеры файлов до очень огромных масштабов. Если Вы описывали API с помощью стандартных средств (просто в комментариях используя официальную спецификацию Open API), то, думаю, Вы понимаете о чём идёт речь. Можно даже посмотреть как выглядят эти громоздкие схемы (а их нужно описывать ещё и в комментариях к коду).
В статье же разбираются инструменты, с помощью которых можно облегчить процесс документирования не используя в комментариях к API стандарт Open API, а использовать удобный синтаксис аналогичный JSDoc (для Go исключение - там не используются многострочные комментарии для описания работы конкретного API), с помощью которого и генерируется документация по спецификации Open API. На мой взгляд именно использование swaggo в значительной степени облегчает документирование кода REST API сервисов.
В добавок, можно оценить go-swagger и swaggo по "звёздочкам" на GitHub, если учесть что эти "звёздочки" определяют полезность и популярность какой-либо зависимости для разработчиков. Если взглянуть на go-swagger, то звёзд там порядка 8.7k, а при просмотре swaggo можно отметить что звёзд там 8.3k. На момент 03.06.2023 разница не велика, а значит обе зависимости были оценены обществом разработчиков как "достаточно полезные". Впрочем, можно тему с оценками развивать и далее, употребив здесь различные контексты и метрики, но пожалуй остановлюсь на этом.
В комментарии Вы отметили, что в коде демонстрационного проекта написанного на Go "оч много антипаттернов", можете привести эти антипаттерны? Сама оценка "очень много" говорит о том, что их там намного больше чем один или даже три. В зависимости от того, что Вы подразумевали под "оч много".
Также, я считаю что демонстрационный проект поддерживает чистую архитектуру. В проекте реализован паттерн Controller Service Repository, с полным соответствием SOLID, местами есть упрощения, но какой код их не имеет. Можно взглянуть на структуру и код проекта более детально, чтобы убедиться в этом.
Для вывода логов у меня подключается и конфигурируется отдельный инструмент - logrus. С его помощью я произвожу вывод логов либо в stderr, либо в файл, расположенный в директории logs (в зависимости от того, есть ли доступ к директории logs и созданию в ней файлов для ведения логов). В демонстрационном примере я не уделил его использованию большого внимания, но если глянуть в main.go, то там используется именно данный инструмент, после своей настройки.
Ну и некоторые детали в демонстрационном проекте были скрыты (переменные окружения, некоторые конфигурационные файлы и миграции к базе данных). Их можно увидеть в .gitignore.
В добавок относительно чистой архитектуры пару слов. Она сейчас достаточно популярна, но не есть "таблетка от всех бед". Можно сделать "чистую архитектуру" такой, что потом команда разработки (коллеги) точно "спасибо не скажут". Сейчас она на хайпе, но до этого были популярны другие принципы, подходы и концепции. Не всегда то, что популярно должно быть в каждом проекте. Нужно вдаваться в детали конкретного проекта. И не всегда "забить" - это плохо. Иногда лучше даже "забить".
Да, Вы правы. Формулировка "конвертирование комментариев в коде в документацию" была бы более понятна новичкам, однако я посчитал что мой посыл понятен, так как этим комментариям я уделяю большое внимание (особенно проекту с кодовым названием NEJ).
Также в статье я описываю, что необходимо для генерации документации по комментариям выполнять определённую команду (они разные для обоих проектов). Эта команда является в своём роде "чёрным ящиком". Но в статье я и не преследовал раскрыть более подробно функционал генерации, каким образом происходит генерация, не затрагивал алгоритмы и не опускался на нижние уровни предоставляемой абстракции.
Из статьи можно сделать выводы о том, что для разных технологических стеков есть разные пакеты, которые облегчают генерацию документации Swagger по коду. На стеке Node.js, Express.js, JavaScript (NEJ) - это многострочные комментарии, а на стеке Golang, Gin (GG) - это однострочные комментарии. Я также делаю акцент на их разнице.
На счёт "магия пропадает" могу сказать следующее. Я не просто так упоминал в статье архитектурный паттерн Controller Service Repository. Дело в том, что в большинстве случаев при документировании API через Swagger комментируют именно самый верхний слой - контроллеров. В статье я рассказываю о том, что в проекте с Express.js этот слой выделяется в Controllers, но по факту комментарии пишутся в routers, т.к. именно там идёт связывание маршрутов с методами контроллера. Например, для NEJ это выглядит следующим образом:
/**
* Авторизация пользователя
* @route POST /auth/sign-in
* @group Авторизация (пользователь) - Функции для авторизации пользователя
* @param {SignInDto.model} input.body.required Входные данные
* @returns {AuthDto.model} 200 - Авторизационные данные пользователя
* @returns {ApiError.model} default - Ошибка запроса
*/
router.post(
AuthRoute.signIn,
[
check('email', 'Введите корректный email').isEmail(),
check('password', 'Минимальная длина пароля должна быть 6 символов')
.isLength({ min: 6 }),
check('password', 'Максимальная длина пароля равна 30 символам')
.isLength({ max: 30 })
],
authController.signIn
);
От их расположения в NEJ мало что зависит, важно чтобы в options были прописаны к ним пути.
Однако, к чему я это. В самый верхний слой редко требуется внесение каких-либо правок. По сути это модель "чёрного ящика" - какая-то информация входит в него, а какая-то выходит и это всё что мы знаем. Это происходит благодаря чёткому разделению ответственности между слоями (про SOLID я также упомянул, хоть и косвенно). А потому достаточно определить входные и выходные данные. Как там внутри бизнес-логика будет реализована - нас мало интересует, мы не преследуем цель документирования бизнес-логики, документирование API и бизнес-логики - разные вещи, а последняя как раз часто и меняется, что может выливаться в историю "наш код не имеет ничего общего с документацией".
Достаточно лишь обновлять комментарии в верхних слоях, определять входные и выходные данные, описание, группировку и другое что потребуется при документировании API.
Статья рассчитана не на новичков, я этот факт подчеркнул меткой сложности как "средней".
Идея разработки универсального компонента header достаточно интересна для frontend-разработки.
Однако, у меня есть некоторые замечания к статье и проекту, которые могли бы Вам помочь улучшить как качество статьи, так и разрабатываемый проект.
Прежде всего стоит отметить, что в области frontend-разработки на React.js существует достаточно большое множество UI-библиотек, в которых реализованы наиболее используемые компоненты при разработке веб-приложения.
Например, MUI и Mantine. Это две достаточно распространённые библиотеки, в которых есть множество компонентов, которые можно уже использовать с поддержкой в той или иной степени адаптивности на разных устройствах и разных языков (JavaScript/TypeScript).
С помощью UI-библиотек и их возможностей можно собрать отличный компонент header, затрачивая при этом не много усилий. Для разработки langing pages или MVP эти библиотеки очень помогают. Рекомендую попробовать поработать с данными библиотеками и, возможно, интегрировать их в свой npm-пакет.
Также, могу предложить как за идею разработать веб-приложение конструктора header'ov, который бы мог собирать header любой сложности и формировать отдельный npm-пакет на выходе. Это бы позволило каждому разработчику с помощью подобной интерактивности делать header чисто с помощью визуальных инструментов. В этом смысле такой мини-конструктор был бы небольшой CMS-системой, ориентированный на генерацию React компонентов, в частности - header'ov.
Написание технической статьи - это творческий процесс, при котором автор делится с аудиторией или обществом какими-то полезными, интересными идеями, разработками, и так далее. На данном сайте есть множество инструментов, которые могут разнообразить Вашу статью и добавить ей свою "изюминку" в последовательности изложения или оформления.
Что можно было бы добавить в Вашу статью? Например, основное изображение статьи (сейчас его нет). Можно придумать самое разное изображение, не обязательно следовать передовым техникам рисования и дизайна.
Также, можно добавить спойлеры, для чрезмерно заинтересованных читателей, чтобы они удовлетворили свой интерес раньше прочтения всей статьи или до момента разбора того или иного момента.
И просить о добавлении "звёзд" статье, я очень не рекомендую, поскольку сообщество на данном сайте саморегулирующееся и моя личная статистика прочитанных статей показывает, что такое "прошение" часто приводит к обратному результату. За "звезду" нужно сделать отличную статью, написать её интересно, а также хорошо оформить.
Хотелось бы также обратить внимание на возможности улучшения кода Вашего пакета.
В том, что Вы используете JavaScript, а не TypeScript, который сейчас достаточно популярен при разработке на React, нет ничего плохого, и ощутимой разницы не будет до момента, пока Ваш пакет не разрастётся до тысяч файлов, в каждом из которых осуществляется работа с разными моделями, DTO или классами. Переход на TypeScript обоснован тогда, когда проект действительно планируется большим и команда проекта также будет расширяться. Одним из плюсов использования данного языка в проекте - долгосрочная поддержка кодовой базы и более удобный мониторинг ошибок в проекте. В некоторых моментах использовать JavaScript даже удобнее, чем TypeScript. Никто не мешает Вам их смешивать в одном проекте. Переписать код с TypeScript на JavaScript можно достаточно легко, как и сделать обратное действие. Рекомендую с TypeScript ознакомиться и попробовать его на практике.
В настоящий момент времени ссылки в "чистом виде" всё реже и реже используют. Очень часто приходится иметь "под рукой" какую-то логику, которая бы определяла маршрутизацию по всему сайту. Header, в этом отношении, не является исключением.
Сейчас популярным решением в организации маршрутизации по веб-приложению является npm-пакет ReactRouter. Он позволяет гибко настроить маршрутизацию, внутри веб-приложения и отслеживать переходы по ссылкам, ставя в соответствие конкретные функциональные компоненты. Он очень удобный, потому я рекомендую Вам с ним ознакомиться и использовать в Вашем npm-пакете. Возможно, стоит добавить поддержку встраивания header'a в логику частого какого-либо проекта, использующего ReactRouter.
Для стилизации компонент принято использовать определённый подход. Это может быть css modules, или styled components (два наиболее распространённых подхода по стилизации). В чистом виде css использовать не рекомендуется, так как такой подход в будущем может навредить проекту. Например, добавил какое-то новое свойство в css одном файле, а изменилось не на одной странице, как предполагалось, а на всех страницах. И потом "гадай" где же ошибка. По этой ссылке перечислены способы стилизации компонент, рекомендую с ними познакомиться и попрактиковаться в их применении.
Также, рекомендую немного поправить оформление кода. Например, следовать определённому порядку импортов. Хороший порядок импортов приведён по этой ссылке.
Рекомендую также ознакомиться с курсом по React-разработке, в котором хорошо разбираются моменты по форматированию кода и улучшению структуры проекта. Думаю это будет полезно.
Не стоит забывать о тестировании кода и предоставлении гибкого интерфейса для кастомизации компонентов или его частей.
Что ж, на этом мои замечания себя исчерпали, желаю Вам успехов!
Спасибо что поделились своими наработками с аудиторией)
Да, здесь используется механизм блокирующего кода. Устройство контроллеров организованно таким образом, что они в большинстве своём используют в качестве возвращаемого типа IResult, а не Task<IResult>, что было бы уместно при реализации механизма неблокирующего кода.
Такое "упрощение" механизма контроллеров было сделано с допущением, что данный проект по большей части демонстрационный, однако при использовании исходников данного проекта конечно стоит учитывать дополнение всех контроллеров возвращаемым типом Task<IResult>.
В дополнение, могу сказать что такие ООДБ как Perst и db4o не поддерживают асинхронных операций и все операции происходят в одном потоке, что является одним из недостатков избранных ООБД. Однако для работы с MongoDB асинхронные операции предусмотрены, но они не были использованы в данной работе. Одной из причин для этого было обобщение способа взаимодействия с базами данных. В статье я также привёл аналогию между корневым объектом Perst и контекстом MongoDB.
Довольно интересный вопрос каким образом менялся образ "настоящего айтишника" в профессиональных кругах с течением времени (в большей его части). Раньше такого понятия вообще не было, оно появилось (по большей части из-за СМИ) сравнительно недавно. И в разных социальных кругах, в разных профессиональных сообществах это понятие может быть сформулировано вообще по разному.
На этот образ также влияет и прогресс в разработке инструментов разработчика, языков программирования, компиляторов, IDE, различных утилит и пакетов. Сейчас реализовать авторизацию по JWT, организовать связь между клиентом и сервером по WebSocket'ам, написать свой сервер REST API или даже сделать свою игру стало проще простого. Раньше приходилось больше изучать и больше практиковаться, чем сейчас.
Титанических усилий стоило разработать Nginx, Unity, Unreal Engine, Node.js, Laravel, Django, Visual Studio (Code || Community), Intellij IDEA, PyCharm, Android Studio и др. Это одни из немногих технологий, которые позволяют нам видеть сегодняшний мир "айти" таким, какой он есть. И эти технологии создали люди, без участия ИИ ассистентов или помощников. Другой вопрос - за счёт чего были созданы эти разработки? За счёт большого числа времени, проведённого за изучением работы сетей, низкоуровневого / высокоуровневого программирования, изучения различных операционных систем и их архитектур. За счёт большого числа потраченного времени на разработку, отладку и тестирование разработок. За счёт определённого бюджета, потраченного на разработку и ещё за многое другое.
Современному бизнесу выгодно вкладываться в проекты, которые можно сделать быстро, также быстро запустить, протестировать гипотезу и начать как можно быстрее продавать свой продукт. Редко кто делает что-то качественно и на совесть, большая часть этого рынка "разгоняется", тем более теперь, когда появились большие языковые модели, различные AI-сервисы и многое другое. Это позволяет делать что-то "на скорую руку" не вдаваясь в детали реализации тех или иных функций и в дальнейшем пользоваться правилом "работает - не трогай".
Бизнес в IT сфере имеет большое влияние. И именно он может определять что вкладывается в понятие "настоящий айтишник" здесь и сейчас. Он может решить, что написание промптов это и есть настоящее "айти", а те кто "умеет профессионально писать промпты к ИИ, хорошо и грамотно формулирует технический текст" явно обладает классными и профессиональными навыками в IT чтобы считаться "настоящим айтишником". Бизнес может сделать из опытных низкоуровневых программистов на Assembler или Си "профессиональных промпт-инженеров для языка Assembler и Си, работающих с ChatGPT", потому что он может платить вторым гораздо больше, чем первым.
Бизнес может "пропагандировать", продвигать и развивать свои идеи об образе "настоящего айтишника" в массы и никто не сможет этому помешать, потому что помогать бизнесу будут такие же "настоящие айтишники". Бизнес может превратить в "луддитов" тех специалистов, которым просто нравится их работа, нравится писать программный код и они кайфуют от этого. Потому что такие "луддиты" бизнесу не выгодны. Они не будут использовать ChatGPT или другие AI-сервисы чтобы добиться максимально быстрого результата. Они не будут по картинкам AI "двигать квадратики, перетягивать стрелочки". Они не будут всю смысловую нагрузку о задаче делегировать на AI, чтобы он решал куда нужно кликнуть мышкой, что там написать и что сделать, чтобы добиться такого то результата. Потому что "луддиты" (в современном понимании бизнеса) - это и есть "настоящие айтишники".
Они сами пишут программный код, сами проектируют и выстраивают программную архитектуру, сами думают над своими задачами и сами же их решают. Сами организуют своё рабочее место, своё рабочее пространство и свой рабочий день со своими задачами. Они не против AI, но и не за то, чтобы полностью в свой рабочий процесс его встраивать. Их максимум - использование AI как умный справочник. Это реальные профессионалы, которых к 2035-ому году будут единицы, поскольку понятие "настоящий айтишник" будет изувечено до основания, а "луддиты" будут фигурировать в различных карикатурах, анекдотах и статьях по типу "Луддит не смог запрограммировать игру за 24 часа, в то время как XXXGPT сделал это за 1 минуту!".
Когда ты делегируешь всю смысловую нагрузку на AI (а, я уверен, к 2035-ому году всё именно так и будет, с учётом тенденции развития идей "бросайте код, пишите промпт!"), то ты лишаешь свой мозг возможности развиться. В каком-то смысле человек, который сам ничего не разрабатывает, не решает, а делегирует всё это AI тренирует его, а не себя. Себя такой человек никак не развивает, только если в "написании грамотных и профессиональных промптах". И можно сколь угодно говорить "ну те же написал текст, значит ты подумал, пофантазировал, придумал и просто сказал LLM что ей надо делать, значит ты вырос над собой" - это всё равно будут пустые слова, которые имеют мало общего с настоящим положением дел (хотя бы с той же нейробиологией). Решение задач программных / математических / физических / научных и литературных имеют довольно много различий. Одно дело написать с 0 аналог Nginx'а на C++, а другое написать фантастику, которая бы заинтересовала людей, но которая имеет много различий с реальностью (в том числе с абстрактными структурами, которые люди в нашем мире используют для улучшения своей жизни).
Можно даже ввести понятие "современный ИТ-луддит", потому что очень часто я вижу как люди в комментариях, в статьях по теме типа "ИИ заменит программистов" пишут, что-то вроде "все кто против прогресса - луддиты" или "всех заменят, а те, кто не хочет заменятся или меняться - луддит".
Современный ИТ-луддит (warning: в это понятие я вкладываю свой смысл и не навязываю его никому) - это человек, который хочет, может и будет думать, рассуждать и решать задачи с помощью своего мозга и заложенного в него интеллекта, а главное - ему это нравится. У данного человека есть и будет своё мнение, которое сформировано в результате приобретения им определённого опыта и навыков, а не встроено в его мозг с помощью "ИТ-курсов от передовых бизнес-компаний". Его знания приобретены в результате практики и прочитанной технической литературы, а не просто необдуманной копипасты с интернета или с ChatGPT. ИТ-луддит уважительно относится к своему интеллекту и поддерживает его в тонусе.
Я ни в коем случае не хотел очернить как-нибудь бизнес или AI, мне самому нравится изучать Machine Learning, архитектуру GPT и разрабатывать модели на Python, да я даже учусь по этому направлению и планирую через год работать в этой сфере или смежной с ней. Просто я считаю, что забывать о том, кто такой "настоящий айтишник" не стоит. У каждого это понимание своё, но транслироваться в массы будет наиболее выгодное для текущего времени, что может огорчать и выводить на эмоции и об этом не стоит забывать.
Не совсем понял что Вы тут имели ввиду. Низкоуровневая оптимизация критически важных или просто важных функций используемых в JavaScript были и есть возможны без развития ИИ. Достаточно, например, по изучать открытый код популярного для JavaScript движка V8 - https://github.com/v8/v8. Он, правда, написан по большей части на C++, но всё равно там есть за что ухватиться. Например, выбор и реализация стратегии сборки мусора на JavaScript. Есть ведь куча стратегий (итерационная, по поколениям, "в свободное время") и как-то это нужно всё оптимизировать. У каждого JavaScript движка есть свои внутренние механизмы для этого и они написаны именно с целью оптимизации и увеличения скорости выполнения JavaScript кода. Или хороший пример Node.js (https://github.com/nodejs/node) там вообще сплошь и рядом использование C/C++ модулей в JavaScript (на базе Node.js). Это всё было возможно задолго до развития ИИ.
В каком именно? Не совсем ясно откуда появились в статье "очки" и каким образом они считаются. Не понятно вообще как в статье пришли от темы ускорения JS до оценки по каким-то очкам популярных JavaScript-фреймворков.
А есть какая-то статистика? Просто чтобы такое утверждать, нужно либо в буквальном смысле глазами наблюдать большое число таких прецедентов, либо опираться на какое-либо исследование. Упоминания ни о том, ни о другом в статье нет.
Не стоит оценивать по скорости компилируемые и интерпретируемые языки программирования, т.к. это две совершенно разные категории и у компиляторов и интерпретаторов стоят разные задачи и возможности вообще, исходя из определённых архитектурных ограничений. Например, движки JavaScript (в большинстве случаев) реализуют Event Loop, который "делает этот язык" (на уровне пользователя) более медленным, чем тот же C, потому что поочерёдное выполнение макро- и микро- задач не может не накладывать отпечаток на скорость. Можно предположить, что если реализуют компилятор для JavaScript, который схож по возможностям с каким-нибудь компилятором С/C++, то скорость будет +/- одинаковой (естественно урезав некоторый функционал из JavaScript по типу EventLoop). Тогда это уже будет не JavaScript, а компилируемый CJavaScript и он будет походить на Go.
Общее впечатление таково, что не низкоуровневые оптимизации стали возможны благодаря развитию ИИ, а эта статья, т.к. есть много вопросов относительно её качества.
Обычно секреты своего успеха не раскрывают... теперь автор этой статьи может воспользоваться Вашей наводкой и у Вас появится новый конкурент в его лице, опасно :)
Не информативные, не нужные, не интересные статьи / посты / мнения по типу
Рак, убивающий Хабр, ака «подпишитесь на мой телеграм-канал» / Хабр (habr.com)
Тоже уже достали. Сделана как статья, хотя механизм постов уже есть и можно при желании на пост и поменять, хотя смысловая нагрузка там будет точно такой же - нулевой, но вот пожаловаться "какие авторы с телеграм-каналами плохие" - хоть каждый день.
Что плохого в публикации в своём труде ссылок на свои социальные сети / каланы и прочее? Что плохого? Почему это "рак"? И почему это можно оправдать "годными корпоративными авторами"?
Абсолютно не справедливо агрессивно реагировать на то, что авторы публикуют на хабре ссылки на свои телеграм каналы. Это проблема не авторов, а вас самих. Что-то, видимо, тригерит у пользователей, когда они читают "подписывайтесь ...".
В какое время мы живём? Во время, когда продвижение решает многое. Уже давно пора привыкнуть к тому, что на публичных ресурсах люди будут продвигаться и для этого нужно в своих материалах оставлять ссылки на себя.
Даже при написании научных статей люди оставляют ссылки на работы, которыми пользовались - библиографический список называется. Возможно между библиографическим списком в научных статьях и сегодняшним "трендом на продвижение" можно составить корреляцию, полагаю что она тут есть, в некотором эволюционном или переносном смысле.
Любой человек, пишущий на хабре, так или иначе продвигается. И ничего Вы с этим сделать не можете (как бы не хотели). Ни Вы, ни кто либо ещё. Даже без оставления ссылок на телеграм-каналы идёт продвижение. Так, а смысл тогда быть противником продвижения? Вы не находите это смешным? Мы все здесь о себе в той или иной мере заявляем. Заявляем что мы можем написать техническую статью, что мы разбираемся в интересующей нас теме (или не очень), что мы можем и делаем. Люди пишут статью для разных целей.
Могу подкинуть новую идею для "мнения" - "Рак, убивающий Хабр, ака "написание технической статьи"", потому что любая техническая статья - это продвижение.
Автор ссылки на себя оставил в самом конце статьи, содержание статьи хорошее, но дизлайки она получила не заслужено. Просто потому что "телеграм канал, ааа, триггерит".
Желаю всем встречаться с триггерами только когда пишете SQL-код для работы с базой данных, а статьи и "мнения" оценивать объективно.
Я тут с Вами не соглашусь. Не то, чтобы я "профессионал" в написании статей, но кое-какой опыт всё же имею и Ваше утверждение "мусор на тематическом ресурсе" мне напомнило о недавней статье, которая Вашему утверждению полностью соответствует, но при этом это одна из самых "залайканных" статей, которые я на этом ресурсе видел:
Я программист, и я тупой / Хабр (habr.com)
Уже судя по названию можно сделать вывод, что статья "мусорная" и не несёт какую-то пользу обществу, вообще никакой, при этом оставаясь в нашем домене (ИТ). А прочитав эту статью можно вообще сделать вывод, что это пост. Анегдот ещё в том, что этот "мусорный пост" (я не знаю как его иначе назвать) является переводом! В этом посте человек просто жалуется на то, что он "тупой" используя при этом "крутые технические термины" типа "распределённый кэш", "микросервисы" и другое.
Здесь автор хотя бы старался написать добротную статью, подумал над оформлением, даже задел тему с ИТ связанную (как ни крути, но популярность no-code растёт и я лично знаю группу разработчиков, которые используют Bubble для решения своих задач и используют его успешно), а в одной из самых "залайканных" статей этого нет. Ни хорошего оформления, ни интересной истории (а история рассказанная в статье действительно интересна), ничего.
И ссылка на телеграм канал даётся в самом конце статьи и никак не обязывает Вас или других на автора подписываться и никаких "неэтичных" поступков автор не совершил, но комментарии с этим "замечанием" получают всё же плюсы. Это какой-то сюр.
Я не завидую "мусорному посту" с большим числом лайков, я просто призываю читателей быть объективными при выставлении минусов таким статьям. Авторам нужно давать второй шанс или вообще их не читать, если отдельные индивидуумы вам не интересны.
Но эта статья вообще не обосновано получила -33. Может технических деталей тут нет, но согласитесь, это гораздо лучше сделанная работа чем "мусорный пост", ссылка на который представлена выше?
И ничего нет такого, что люди дают ссылку на свои контакты - все тут для продвижения, самовыражения и прочих целей связанных с личными интересами (кроме комментаторов, которые пишут мусор и не сделали ни одной статьи, но других "поругать" - хлебом не корми).
Товарищи, будьте объективны, только благодаря вашей оценки "мусорные посты" продвигаются вверх или вниз. Этот пост к этому числу не относится (см. пост выше).
Перехватить синтетическое событие на этапе погружения можно. Это делается с помощью добавления постфикса Capture в атрибут обработчика какого-либо события в JSX.
Например, следующий код перехватывает событие клика на этапе погружения и всплытия:
Ну и в консоли браузера вывод будет правильный:
Подробнее о SyntheticEvent можно почитать здесь: https://ru.react.js.org/docs/events.html
Рекомендую автору поправить этот момент, т.к. синтетические события на этапе погружения обрабатывать (или перехватывать) можно.
Вообще, можно разделить критику на две группы (так проще): токсичная и здоровая.
Токсичная критика в целом не несёт ничего хорошего как для автора статьи, как для самой статьи, так и для автора токсичного комментария изложенного выше.
Напротив же здоровая критика способна направить автора на продолжение исследования темы, может расширить его кругозор, она помогает дополнить рассматриваемую тему, улучшить саму статью.
Я считаю, что Ваша критика не совсем здорова. Ваши высмеивания издержек из моего труда (которые, к слову, ошибочны) это демонстрируют.
Обругать можно что угодно и быть токсичным проще простого. Вообще как "нефиг делать". Вы попробуйте быть терпеливым, сдержанным, уметь направить других людей в нужном направлении. Это сложнее всего. И к этому, я считаю, нужно стремиться.
Теперь к самому комментарию.
Я ничего нового не изобрёл. Укажите где Вы увидели путаницу между событиями и обработчиками событий? Признаюсь, я проверял статью несколько раз и не увидел, чтобы где-то было это нарушено, потому что если столько раз писать о событиях и иметь определённый эмпирический опыт в их написании, то невольно можно ошибиться. Я разделял в статье события и их обработку. Укажите пожалуйста место, где я этого не сделал - поправлю.
Где я написал, что синтетические события это "круто" и что они "лучше" нативных? Вообще не к этой статье относится. Может прочитали что-то одно, потом пришли почитать эту статью и у Вас всё смешалось? Такое бывает, это нормально. Я указал на чёткую разницу между синтетическими и нативными событиями. И то, что для решения описанной мной проблемы пользователь может захотеть переписать функциональные компоненты на классовые - это просто факт. Ну нет охоты у читателя переподписку делать, проще классовые компоненты сделать. Этот пункт Вы просто сами придумали (кроме утечки памяти, это в статье действительно было).
Где я отказывал в праве браузерному событию называться нативным? Я просто высказал своё мнение. Внимание, это было моё мнение, а не навязывание какой-то позиции. Я никакой позиции своей тут не навязываю. Спецификация это одно, а реализация этой спецификации под разные браузеры - это другое. Именно это я и отразил в своём скромном мнении о нативных событиях.
Нативность - не мой термин. Он существует с тех пор, как люди стали разграничивать высокоуровневые вещи и низкоуровневые в контексте программной (и не только) реализации.
Опять придуманный пункт. Я поясняю почему он обработчик нативного события не работает, а синтетического - работает. Почитайте комментарии выше, может это Вам что-то даст в понимании (в том числе мои цитаты к статье).
Кстати, если Вы называете эту особенность "тривиальным багом", то Вам стоит лучше разобраться с этой механикой, потому что это не баг и он не тривиальный.
Речи о замыканиях тут вообще не шло. Речь шла о захвате контекста компонента. Не более. На счёт "мемоизации с багом" - ну, как свой eslint настроите, так он и будет работать. У меня всё работает так, как я и ожидаю. Рекомендую ознакомиться с темой мемоизации и кэширования в React.js (+ чистые функции), может быть Вы к такому коду отнесётесь более сдержанно, потому что в массив зависимостей useEffect'а добавлять обёрнутую в useCallback функцию можно, иначе ничего бы не работало :).
Не согласен с Вами. Одна из целей статьи - "повышение осведомлённости" о такой проблеме. В своё время я часто забывал об этой проблеме и совершал ошибки. Если бы где-то было понятное описание этой проблемы и способу её решения - я был бы рад. Не нашёл таких статей - написал сам. Теперь любой желающий может найти эту статью в поисковике и ознакомиться с проблемой, её решением и исключениях. Может быть, даже получит мотивацию для дальнейшего исследования этого вопроса.
Вы если нашли ошибку в статье - напишите критику с указанием ошибки и пояснениями (если Вам есть что рассказать), а не с неаргументированным высмеиванием перекрученных издержек из статьи. От этого и Вам будет польза (потому что Вы лучше разберётесь в этом вопросе) и содержимому статьи (потому что результат здоровой критики не внести в статью было бы небрежно) и лично мне (т.к. я тоже как и Вы разберусь в этом вопросе лучше).
Если уж совсем не поняли - спросите в комментариях, уточните что автор имел ввиду в конечном счёте. А то есть риск формирования у Вас выводов, которые максимально бесполезны и вредны. И Вам и людям, которые их прочитают.
Например, в комментарии ниже автор указал на другой аспект этой проблемы - память. Мне захотелось внести это в статью, что я с удовольствием сделаю, чтобы у читателя было больше возможностей разобраться с этой темой.
А Ваш комментарий в текущем виде... ну, не знаю, пользы от него нет.
Ругать можно что угодно, сложно найти в чём угодно хорошее, как и положительно влиять на авторов статей, чтобы они писали их лучше :)
С первым утверждением частично согласен. Конкретно события - ни при чём. Тут причастны обработчики данных событий, о чём, собственно, и написано в статье.
В целом то, что Вы описали (проблема с функциональным компонентом) есть в статье, только я оперирую введённым понятием "контекст React-компонента" и не упомянул ничего про память, думаю это хорошее дополнение. Суть проблемы не меняется - обработчики синтетических событий находятся в JSX-коде и при перерисовке они захватывают все актуальные состояния, а при обработке нативных событий этого не происходит и внутри обработчиков мы всегда имеем начальное значение состояния. Да и не всегда оно начальное. Если использовать hot reload, то можно добиться такого поведения, что в примере из статьи значение currentValue установится на какое-нибудь рандомное единожды, но не более.
Я использовал термин "контекст React-компонента" потому что обработчики событий всё-таки захватывают, например, refs. Поэтому нельзя сказать что вообще все ссылки в этом обработчике не захватываются. Захватываются, только ссылки refs. Ну и ещё можно дополнить этот список "исключений" по мере необходимости.
Ну, а сам "не захват" части контекста компонента происходит как раз из-за того, что Вы описали - ссылки на функцию не теряются, а новые уже не добавляются в обработчик нативного события. Отсюда и есть необходимость переподписки.
По-видимому в классовых компонентах этот пример работает потому что ссылка на функцию обработчик постоянно меняется и нет даже необходимости делать переподписку на обработку нативного события.
В статье показана разница между синтетическими и нативными событиями. При описании проблемы я указываю на то, что обработка синтетических событий определена в JSX-коде и все эти обработчики захватывают актуальный полный контекст компонента (внутри них актуальные ссылки на состояния).
Пример с useEffect без массива зависимостей тут не очень подходит, т.к. переподписка на события будет при вообще любом рендере (необязательно при изменении стейта value). В общем-то можно использовать в массиве зависимостей и просто стейт value:
Это даст точно такой же эффект, но я написал программный код таким образом, каким посчитал более правильным - через мемоизацию. Сразу понятно что мы кэшируем обработчик, кэш может меняться и если он поменялся - делаем переподписку.
Есть проекты, в которых используется подход с изолированными css-стилями (так называемый css-modules). При таком подходе имена стилей генерируются автоматически и при подключении их к проекту не возникает никаких конфликтов (если вдруг однажды не будет сгенерировано имя стиля, который уже встречается в проекте... но, это маловероятно). Считать ли такие стили "костылями", только потому, что они позволяют локально переопределять внешний вид элементов? Очень сомневаюсь. Я бы предложил исправить название этого понятия на "локальный стиль", чтобы не вводить в заблуждение читателей, которые только знакомятся с frontend разработкой.
При использовании готовых решений (библиотек компонентов, например) часто приходится переопределять стили стандартных компонент для того, чтобы они соответствовали дизайну (и это нормально). И да, без className тут не обойтись, если нужна какая-то "сложная" визуализация. Библиотеки UI-компонент предоставляют только "базовый" набор часто используемых компонент, но если нужно добавить свои изменения - тут без инструментов для кастомизации не обойтись. Это именно инструмент кастомизации, а не "баг" или "фича". Можно это даже считать своеобразным компонентным API (думаю, что так даже более корректно).
Я считаю, что если проекту не хватает возможностей UI-библиотеки, то стоит либо свою библиотеку разрабатывать (с нуля), либо создавать свои компоненты на основе уже готовых с переопределением стилей через classNames, и лучше это делать именно с помощью сравнительно безопасного подхода css-modules (или styled-components). И это не должно считаться "костылём". Готовые решения не панацея, в любой момент может потребоваться изменить поведение уже готового компонента, это только вопрос времени.
Добрый день.
Поток можно интерпретировать по-разному, с учётом обстоятельств, контекста или каких-нибудь общепринятых норм и правил. В программировании поток - это одно, в каких-либо организационных вещах - другое.
В моей статье поток был рассмотрен с точки зрения "течения". То есть фактически можно сравнить поток с потоком реки. А поток реки может ассоциироваться с какими-то постоянными или циклическими процессами. В данном случае поток - это циклический процесс.
Таким образом поток в статье - это какой-либо циклический процесс, в данном случае - анализ и документирование проекта, в котором некоторые элементы повторяются раз за разом (например, комментирование файлов исходного кода или процесс добавления новых API в Swagger UI).
Добрый день.
В своей статье я не даю советы об использовании той или иной технологии - это индивидуальный выбор каждого конкретного разработчика и каждой конкретной команды, и выбор этот зависит от многих факторов.
REST API можно реализовать на чём угодно: Gin, Nest.js, Node.js, Django, Laravel, Flask, Spring Boot и так далее - всё зависит от тех самых "многих факторов", на которые я ссылаюсь выше. И документирование API сервиса (или приложения) можно разными способами. Можно действительно писать громоздкие комментарии, точно следуя стандарту Open API, проверяя при этом каждую модель и за счёт этого увеличивать размеры файлов до очень огромных масштабов. Если Вы описывали API с помощью стандартных средств (просто в комментариях используя официальную спецификацию Open API), то, думаю, Вы понимаете о чём идёт речь. Можно даже посмотреть как выглядят эти громоздкие схемы (а их нужно описывать ещё и в комментариях к коду).
В статье же разбираются инструменты, с помощью которых можно облегчить процесс документирования не используя в комментариях к API стандарт Open API, а использовать удобный синтаксис аналогичный JSDoc (для Go исключение - там не используются многострочные комментарии для описания работы конкретного API), с помощью которого и генерируется документация по спецификации Open API. На мой взгляд именно использование swaggo в значительной степени облегчает документирование кода REST API сервисов.
В добавок, можно оценить go-swagger и swaggo по "звёздочкам" на GitHub, если учесть что эти "звёздочки" определяют полезность и популярность какой-либо зависимости для разработчиков. Если взглянуть на go-swagger, то звёзд там порядка 8.7k, а при просмотре swaggo можно отметить что звёзд там 8.3k. На момент 03.06.2023 разница не велика, а значит обе зависимости были оценены обществом разработчиков как "достаточно полезные". Впрочем, можно тему с оценками развивать и далее, употребив здесь различные контексты и метрики, но пожалуй остановлюсь на этом.
В комментарии Вы отметили, что в коде демонстрационного проекта написанного на Go "оч много антипаттернов", можете привести эти антипаттерны? Сама оценка "очень много" говорит о том, что их там намного больше чем один или даже три. В зависимости от того, что Вы подразумевали под "оч много".
Также, я считаю что демонстрационный проект поддерживает чистую архитектуру. В проекте реализован паттерн Controller Service Repository, с полным соответствием SOLID, местами есть упрощения, но какой код их не имеет. Можно взглянуть на структуру и код проекта более детально, чтобы убедиться в этом.
Для вывода логов у меня подключается и конфигурируется отдельный инструмент - logrus. С его помощью я произвожу вывод логов либо в stderr, либо в файл, расположенный в директории logs (в зависимости от того, есть ли доступ к директории logs и созданию в ней файлов для ведения логов). В демонстрационном примере я не уделил его использованию большого внимания, но если глянуть в main.go, то там используется именно данный инструмент, после своей настройки.
Ну и некоторые детали в демонстрационном проекте были скрыты (переменные окружения, некоторые конфигурационные файлы и миграции к базе данных). Их можно увидеть в .gitignore.
В добавок относительно чистой архитектуры пару слов. Она сейчас достаточно популярна, но не есть "таблетка от всех бед". Можно сделать "чистую архитектуру" такой, что потом команда разработки (коллеги) точно "спасибо не скажут". Сейчас она на хайпе, но до этого были популярны другие принципы, подходы и концепции. Не всегда то, что популярно должно быть в каждом проекте. Нужно вдаваться в детали конкретного проекта. И не всегда "забить" - это плохо. Иногда лучше даже "забить".
Добрый день.
Да, Вы правы. Формулировка "конвертирование комментариев в коде в документацию" была бы более понятна новичкам, однако я посчитал что мой посыл понятен, так как этим комментариям я уделяю большое внимание (особенно проекту с кодовым названием NEJ).
Также в статье я описываю, что необходимо для генерации документации по комментариям выполнять определённую команду (они разные для обоих проектов). Эта команда является в своём роде "чёрным ящиком". Но в статье я и не преследовал раскрыть более подробно функционал генерации, каким образом происходит генерация, не затрагивал алгоритмы и не опускался на нижние уровни предоставляемой абстракции.
Из статьи можно сделать выводы о том, что для разных технологических стеков есть разные пакеты, которые облегчают генерацию документации Swagger по коду. На стеке Node.js, Express.js, JavaScript (NEJ) - это многострочные комментарии, а на стеке Golang, Gin (GG) - это однострочные комментарии. Я также делаю акцент на их разнице.
На счёт "магия пропадает" могу сказать следующее. Я не просто так упоминал в статье архитектурный паттерн Controller Service Repository. Дело в том, что в большинстве случаев при документировании API через Swagger комментируют именно самый верхний слой - контроллеров. В статье я рассказываю о том, что в проекте с Express.js этот слой выделяется в Controllers, но по факту комментарии пишутся в routers, т.к. именно там идёт связывание маршрутов с методами контроллера. Например, для NEJ это выглядит следующим образом:
От их расположения в NEJ мало что зависит, важно чтобы в options были прописаны к ним пути.
Однако, к чему я это. В самый верхний слой редко требуется внесение каких-либо правок. По сути это модель "чёрного ящика" - какая-то информация входит в него, а какая-то выходит и это всё что мы знаем. Это происходит благодаря чёткому разделению ответственности между слоями (про SOLID я также упомянул, хоть и косвенно). А потому достаточно определить входные и выходные данные. Как там внутри бизнес-логика будет реализована - нас мало интересует, мы не преследуем цель документирования бизнес-логики, документирование API и бизнес-логики - разные вещи, а последняя как раз часто и меняется, что может выливаться в историю "наш код не имеет ничего общего с документацией".
Достаточно лишь обновлять комментарии в верхних слоях, определять входные и выходные данные, описание, группировку и другое что потребуется при документировании API.
Статья рассчитана не на новичков, я этот факт подчеркнул меткой сложности как "средней".
Добрый день.
Идея разработки универсального компонента header достаточно интересна для frontend-разработки.
Однако, у меня есть некоторые замечания к статье и проекту, которые могли бы Вам помочь улучшить как качество статьи, так и разрабатываемый проект.
Прежде всего стоит отметить, что в области frontend-разработки на React.js существует достаточно большое множество UI-библиотек, в которых реализованы наиболее используемые компоненты при разработке веб-приложения.
Например, MUI и Mantine. Это две достаточно распространённые библиотеки, в которых есть множество компонентов, которые можно уже использовать с поддержкой в той или иной степени адаптивности на разных устройствах и разных языков (JavaScript/TypeScript).
Для более подробного знакомства с популярными React UI-библиотеками рекомендую ознакомиться со следующими статьями:
https://blog.logrocket.com/top-10-react-ui-libraries-kits/
https://techrocks.ru/2021/08/25/react-packages-with-ui-components/
С помощью UI-библиотек и их возможностей можно собрать отличный компонент header, затрачивая при этом не много усилий. Для разработки langing pages или MVP эти библиотеки очень помогают. Рекомендую попробовать поработать с данными библиотеками и, возможно, интегрировать их в свой npm-пакет.
Также, могу предложить как за идею разработать веб-приложение конструктора header'ov, который бы мог собирать header любой сложности и формировать отдельный npm-пакет на выходе. Это бы позволило каждому разработчику с помощью подобной интерактивности делать header чисто с помощью визуальных инструментов. В этом смысле такой мини-конструктор был бы небольшой CMS-системой, ориентированный на генерацию React компонентов, в частности - header'ov.
С точки зрения написания статьи, рекомендую Вам ознакомиться со следующей статьей:
https://habr.com/ru/company/habr/blog/262653/
Написание технической статьи - это творческий процесс, при котором автор делится с аудиторией или обществом какими-то полезными, интересными идеями, разработками, и так далее. На данном сайте есть множество инструментов, которые могут разнообразить Вашу статью и добавить ей свою "изюминку" в последовательности изложения или оформления.
Что можно было бы добавить в Вашу статью? Например, основное изображение статьи (сейчас его нет). Можно придумать самое разное изображение, не обязательно следовать передовым техникам рисования и дизайна.
Также, можно добавить спойлеры, для чрезмерно заинтересованных читателей, чтобы они удовлетворили свой интерес раньше прочтения всей статьи или до момента разбора того или иного момента.
И просить о добавлении "звёзд" статье, я очень не рекомендую, поскольку сообщество на данном сайте саморегулирующееся и моя личная статистика прочитанных статей показывает, что такое "прошение" часто приводит к обратному результату. За "звезду" нужно сделать отличную статью, написать её интересно, а также хорошо оформить.
Хотелось бы также обратить внимание на возможности улучшения кода Вашего пакета.
В том, что Вы используете JavaScript, а не TypeScript, который сейчас достаточно популярен при разработке на React, нет ничего плохого, и ощутимой разницы не будет до момента, пока Ваш пакет не разрастётся до тысяч файлов, в каждом из которых осуществляется работа с разными моделями, DTO или классами. Переход на TypeScript обоснован тогда, когда проект действительно планируется большим и команда проекта также будет расширяться. Одним из плюсов использования данного языка в проекте - долгосрочная поддержка кодовой базы и более удобный мониторинг ошибок в проекте. В некоторых моментах использовать JavaScript даже удобнее, чем TypeScript. Никто не мешает Вам их смешивать в одном проекте. Переписать код с TypeScript на JavaScript можно достаточно легко, как и сделать обратное действие. Рекомендую с TypeScript ознакомиться и попробовать его на практике.
В настоящий момент времени ссылки в "чистом виде" всё реже и реже используют. Очень часто приходится иметь "под рукой" какую-то логику, которая бы определяла маршрутизацию по всему сайту. Header, в этом отношении, не является исключением.
Сейчас популярным решением в организации маршрутизации по веб-приложению является npm-пакет ReactRouter. Он позволяет гибко настроить маршрутизацию, внутри веб-приложения и отслеживать переходы по ссылкам, ставя в соответствие конкретные функциональные компоненты. Он очень удобный, потому я рекомендую Вам с ним ознакомиться и использовать в Вашем npm-пакете. Возможно, стоит добавить поддержку встраивания header'a в логику частого какого-либо проекта, использующего ReactRouter.
Для стилизации компонент принято использовать определённый подход. Это может быть css modules, или styled components (два наиболее распространённых подхода по стилизации). В чистом виде css использовать не рекомендуется, так как такой подход в будущем может навредить проекту. Например, добавил какое-то новое свойство в css одном файле, а изменилось не на одной странице, как предполагалось, а на всех страницах. И потом "гадай" где же ошибка. По этой ссылке перечислены способы стилизации компонент, рекомендую с ними познакомиться и попрактиковаться в их применении.
Также, рекомендую немного поправить оформление кода. Например, следовать определённому порядку импортов. Хороший порядок импортов приведён по этой ссылке.
Рекомендую также ознакомиться с курсом по React-разработке, в котором хорошо разбираются моменты по форматированию кода и улучшению структуры проекта. Думаю это будет полезно.
Не стоит забывать о тестировании кода и предоставлении гибкого интерфейса для кастомизации компонентов или его частей.
Что ж, на этом мои замечания себя исчерпали, желаю Вам успехов!
Спасибо что поделились своими наработками с аудиторией)
Доброе утро.
Да, здесь используется механизм блокирующего кода. Устройство контроллеров организованно таким образом, что они в большинстве своём используют в качестве возвращаемого типа IResult, а не Task<IResult>, что было бы уместно при реализации механизма неблокирующего кода.
Такое "упрощение" механизма контроллеров было сделано с допущением, что данный проект по большей части демонстрационный, однако при использовании исходников данного проекта конечно стоит учитывать дополнение всех контроллеров возвращаемым типом Task<IResult>.
В дополнение, могу сказать что такие ООДБ как Perst и db4o не поддерживают асинхронных операций и все операции происходят в одном потоке, что является одним из недостатков избранных ООБД. Однако для работы с MongoDB асинхронные операции предусмотрены, но они не были использованы в данной работе. Одной из причин для этого было обобщение способа взаимодействия с базами данных. В статье я также привёл аналогию между корневым объектом Perst и контекстом MongoDB.