Результати пошуку за запитом: Обучение c
Популярні PHP MVC фреймворки
Автор: Редакция ITVDN
Автор статьи: Влад Кобылянский, архитектор программного обеспечения, разработчик и консультант по технологиям малого бизнеса (Майами, Флорида).
Вопрос: Что сегодня происходит с PHP фреймворками?
В феврале 2017 года я так ответил на этот вопрос:
«В основном все крутится вокруг двух PHP фреймворков - Laravel и Symfony. Особой нужны в использовании CakePHP, Zend, CodeIgniter, Yii и т. д. нет, если вы начинаете новый проект. Только если вы уже знаете эти фрэймворки или у вас в команде есть разработчики которые привыкли работать с ними, тогда причины их использования обоснованы.
Когда начинается реальная разработка, вы должны иметь возможность находить инструменты, плагины, ответы на общие проблемы. С сообществами Laravel и Symfony, с постоянным развитием новых «модулей» или функций, не будет ощущения, что вы остались «в стороне». Одни Laracast (даже если вы не работаете в Laravel) чего стоят! Они просто фантастичны.
Когда заходит речь об интеграции с iron.io или другими SaaS сервисами, поддержке широкого спектра источников данных или о среде разработки – Laravel и Symfony и их расширения намного более продвинуты.
Еще одним достоинством Lumen, является быстрая разработка и прототипирование API для Laravel. При этом это никак не ограниченно для построения больших приложений.Вообще говоря, сегодня мы определенно видим переход к контейнерной архитектуре, где MVC играет гораздо меньшую роль. Все это касается микросервисов, оркестровки и создания приложений как «функций» (AWS Lambda и подобных сервисов). Возможно, пришло время освежить наши навыки Node/JS и GoLang?»
Хотя я в целом доволен этим ответом, сейчас я думаю, что некоторые моменты пришло время пересмотреть.
Прежде чем перейти к таким странным темам, как GoLang, давайте взглянем на тенденции PHP MVC фреймворков.
Я бы сказал, что тенденции, которые мы наблюдали в прошлом, остаются. Laravel продвигается вперед, в то время как большинство остальных фреймворков отстает. В популярности Symfony наблюдается небольшой всплеск, вероятно, из-за долгожданного выпуска Symfony 3. Я попробовал более конкретные поиски для сравнения, такие как «CakePHP 3» или «ZF2», однако они не привели к статистически значимым тенденциям.
На этот раз я добавил CodeIgniter, потому что он оказалася очень популярным. Я получил ряд вопросов о CodeIgniter. Если коротко, CI сейчас не в конкуренции, потому что это не 100% фреймворк MVC. Иначе, чем организованной коллекцией POPO, я это не назову.
Для наглядности представляю вам цитату из руководства CodeIgniter:
«CodeIgniter имеет довольно свободный подход к MVC, поскольку не требуются Models. Если вам не нужно дополнительное разделение или вы обнаружите, что поддерживающие Models требуют большей сложности, чем вы хотите, вы можете их проигнорировать и создать свое приложение с помощью Controllers и Views.»
Когда дело доходит до построения структуры, я просто не согласен с таким подходом. Возможно, это достойный шаблон (отсюда и популярность CodeIgniter), однако должна быть какая-то дисциплина, навязанная фреймворком, иначе конечный продукт в итоге превращается в беспорядочный спагетти-код, завернутый в какой-то «шаблон».
Далее, Symfony 3 привнес некоторые достойные улучшения в разработку и целый ряд новых «фич». Как и многие аналоги PHP, теперь он предлагает микро-фреймворк. ZF3, к примеру, добавил ряд улучшений, таких как поддержка PHP7 (наконец!) и даже стал микро-фреймворком... но, в их руководстве так и говорится:
«Для пользователей Zend Framework 2 MVC, различия с ZF3 незначительны...»
Я действительно надеялся, что они скажут, что различия есть, что было замечательное архитектурное усовершенствование, замечательные новые модули, которые помогают вам разрабатывать все по-современному. Но, увы, по большей части ZF3 по-прежнему похож на ZF2.
Long Story Short
Вот как я вижу мир PHP фреймворков сегодня:
Symfony или Laravel (выбор зависит от того, какую задачу вам нужно решить)
Все остальное
Laravel на первом месте. Объем доступной информации, Laracasts, таланты разработчиков во всем мире, простые реализации шаблонов, интегрированные наборы инструментов тестирования, активная реализация записей в форме Eloquent, облегченная версия в Lumen, развитие Homestead (Vagrant) – все перечисленное способствует фреймворку действительно выделяться и для новых, и для опытных разработчиков.
Однако модели Eloquent могут стать непослушными и довольно большими по размеру, а сервисов Laravel (не путать с микросервисами) можно создать очень много, и вот тут люди начинают думать о реализации Repository, которому здесь не место. Так родился Monolith.
Если вам не нравится активный шаблон записи и вам нужна дополнительная гибкость в репозиториях, или, возможно, вы видите слишком много независимых анонимных функций, тогда используйте Symfony + Doctrine. Рассматриваю ли я Symfony как шлюз для монолитных приложений? В какой-то степени, да.
В целом, я бы не назвал это резким изменением с прошлого года. Тем не менее, нам нужно взглянуть на общую картину: правильно разработанное приложение выходит за рамки чистого MVC; речь идет об инфраструктуре, конвейере развертывания, разъединённой архитектуре. Все это может быть достигнуто в стеке MVC, но нужно быть внимательным, чтобы избежать Monolith.
Приход микросервисов
Раньше я упоминал о распространенности микросервисов и необходимости улучшать навыки GoLang или Node. А в статье о PHP MVC было бы глупо не упомянуть о явно растущем движении к микросервис-ориентированной архитектуре (MOA); и это движение набирает обороты, поверите вы или нет.
Хотя эти два понятия не являются взаимоисключающими, не нужно находить параллели между ними, ведь они действительно представляют собой разные философии. В качестве примера, размещение вашего приложения MVC в одном контейнере и MySQL в другом, а затем объединение их вместе, не обязательно представляет собой надлежащую MOA.
Это, безусловно, лучший подход, чем пытаться установить MAMP, XAMPP или что-либо еще, чтобы заставить ваш компьютер работать с приложением.
Кроме того, это может решить некоторые проблемы, такие как простота запуска локальной среды на разных платформах и, возможно, в некоторых случаях стратегии развертывания, но вы застрянете с монолитным MVC в вашем приложении/контейнере.
Уничтожение Monolith
Микросервисы – это как раз о «разрушении». В то время как MVC обращается к вашей структуре кода и организации, обеспечивая надежный подход к разделению проблем, эта концепция еще больше расширяется контейнерами/сервисами/MOA.
Вместо того, чтобы просто отделять виды (Views) от моделей (Models), вы теперь разделяете каждый «кусок» или логическую единицу вашего приложения на индивидуальную службу, предназначенную для правильной работы с собственными обязанностями.
Если у вашего MVC-приложения есть контроллер «Поиск», действия и соответствующие методы модели, то у нас уже есть пример монолитного приложения.
Напротив, используя подход MOA, у нас будет сервис для каждого из этих процессов. В качестве примера:
Router сервис
Request сервис
Query сервис
DataSource сервис
Response сервис
Но не все эти «сервисы» являются частью стека MVC? Конечно нет. Они являются строительными блоками нашего Monolith.
С MOA каждый сервис работает в рамках собственной среды, а мы, как архитекторы, можем разработать лучший подход к решению конкретного запроса.
В качестве примера, если я должен был бы написать службу обработки изображений в среде Laravel, я использовал бы что-то вроде расширения PHP-GD2, что может быть не самым эффективным способом обработки изображений. Служба C++, которая обрабатывает мои запросы в обработке изображений, может быть намного быстрее и определенно более надежной при масштабировании. И мы могли бы сделать вывод службы обработки изображений и отправить ее в службу DataStore, службу CloudStorage и службу Queue Email.
Решение этой же задачи с кучей скрытых заданий и, возможно, нескольких отдельных приложений MVC и пользовательских сценариев – это то, как разработчики делали это раньше (2 года назад). Время двигаться вперед.
Масштабируемость
Здесь возникают проблемы (или заканчиваются, в зависимости от того, куда вы держите курс). С одной стороны, очень сложно масштабировать Monolith: если вы создадите все больше и больше логики в одном и том же наборе MVC, вы застрянете с хорошо структурированным приложением ужасной сложности. С другой стороны, если вы построите тысячу микросервисов на разных языках, как вы будете управлять этим беспорядком?
Существуют различные инструменты компоновки контейнеров (например, Kubernetes, Swarm, Mesos), услуги по развертыванию контейнеров (GKE и AWS ECS), однако лишь немногие предприятия используют архитектуру Docker. Есть удачные истории в построении инфраструктуры с использованием Docker или других контейнерных технологий (т. е. GKE). Большинство из этих историй исходят от компаний, которые могут позволить себе тратить ресурсы на архитекторов, дефолтов, администраторов баз данных и инженеров. Тем не менее, сейчас идут бесчисленные дискуссии о том, как развернуть хорошо организованный и элегантный MOA.
В любом случае, вы не решите эту проблему самостоятельно, и пока вы не достигнете относительно большого масштаба, эта проблема действительно нуждается в решении. Может быть, сейчас не самое время усердствовать.
Золотая середина на сегодняшний день (даже для тех, кто занимается приложениями меньшей сложности или не такими требованиями к трафику) заключается в том, чтобы разгрузить многие типичные сервисы сторонним провайдерам. Почти все доступно сейчас как сервис. Фоновые задания, обработка изображений, аутентификация, аналитика данных, ведение журнала, отправка электронной почты, системы очереди не обязательно должны строиться в одном стеке MVC, а архитектор должен подумать о том, что может быть выгружено в систему SaaS за небольшую ежемесячную стоимость (т.е. поиск Algolia) или, возможно, специально созданную докерную службу, работающую в облачном пространстве, которая выполняет эту обработку изображений.
Я думаю, важно, чтобы вы не начали перепроектировать весь проект с начала, не сбрасывать все, что у вас уже есть, а выпускать докеры, где это можно сделать. Существуют способы постепенного развертывания вашего проекта/продукта путем разъединения, изучения узких мест в системе (и т.д.) и последующим применением разделения проблем в этих проблемных областях.
Вывод
2017 год принес нам много дискуссий и производственных развертываний, основанных на контейнерах и MOA. Мои размышления о Docker, используя GoLang или Node, не означают, что PHP «умирает» или что-то в этом роде ... Я считаю, что разработчикам нужно оставаться в тренде. Если микросервисы и дальше будут развиваться в том же русле, в котором это происходит сейчас, то почему бы не изучить GoLang? Он идеально подходит (из-за низкой занимаемой площади, скорости и параллельной обработки) для разработки небольших контейнерных приложений. Node и GoLang позволяют создавать небольшие сервисы, которые являются частью более крупного проекта, связывают созданные сервисы и выпускают их как контейнеры Docker, если это необходимо в вашей работе.
Тем не менее, все эти передовые решения и языки не уменьшают значимость и востребованность языка PHP. Разработчикам еще нужны будут стеки MVC и работа с API.
MOA пока не помогает решить архитектурные проблемы на стороне frontend, UI или Views, хотя при этом контейнеры помогают нам избежать работы с Monolith на backend. Мы можем создать чрезвычайно надежное backend-приложение, но оно среагирует на JSON, который каким-то образом должен быть представлен в клиентском приложении. Имеет ли значение, если результирующий объект ответа поступает из РНР кода, URL или от модулей принятия решений и обработки, разделенных интерфейсом обмена сообщениями? Это зависит от Ваших потребностей и требований к вашему приложению.
Мой совет: в этом году учите Laravel, следите за Docker, GoLang и фокусируйтесь на конвейере развертывания. Продвижение от локального небольшого проекта к продакшену должно быть достаточно плавным, особенно при создании приложений MVC.
Оригинал статьи
Введення в розробку програм під iOS. Частина 5
Автор: Volodymyr Bozhek
Здравствуйте, дорогие читатели.
В этом уроке мы научимся:
Добавлять иконку приложения;
Добавлять картинки в приложение. Разберем, как пользоваться “Assets”.
Откройте проект “Warehouse”.
В панели навигатора откройте модуль “Assets.xcassets”.
Нажмите “App Icon”, вы увидите область с контейнерами для добавления иконок приложения.
На рисунке выше нас интересуют два контейнера “iPhone App iOS 7-10 60pt”, тут задается иконка приложения.
В разделе “iPhone Notification iOS 7-10 20pt” задается иконка, которая будет отображаться при получении “Push” уведомлений от вашего приложения в заголовке сообщения.
В разделе “iPhone Spotlight – iOS 5,6 Settings – iOS 5-10 29 pt” задается иконка приложения, которая будет отображаться в диалоге поиска вашего телефона (если приложение под iOS 5 или 6) и в настройках телефона.
В разделе “iPhone Spotlight iOS 7-10 40pt” задается иконка, которая будет отображаться в диалоге поиска вашего телефона.
Теперь давайте разберем, что означают метки “2х” и “3х”. Метки- это размер иконок.
Например, ваша исходная иконка имеет размер “16х16”, для нее будет задана метка “1х”. Соответственно, для метки “2х” будет размер “32х32” (16+16 x 16+16), т.е. в два раза больше исходной иконки под меткой “1х”. Для метки “3х” будет размер “48х48” (16+16+16 x 16+16+16), т.е. в три раза больше исходной иконки под меткой “1х”.
Принято именовать иконки следующим образом:
Иконка с меткой 1х используется для iOS ниже 7 версии. Вам ее не нужно делать, так мы используем язык программирования “Swift” в нашем приложении и доступен он, только начиная с версии “iOS 8”, не ниже. В “iOS” ниже версии 8 доступен для использования язык программирования “Objective C”, его я не буду разбирать вообще, поскольку у него не удобочитаемый синтаксис и для новичков он будет сложным. Т.е., должно быть в таком формате “[Имя исходной иконки][Размер в “pt”][Метка].[Расширение файла иконки]”.
Таблица с размерами и метками иконок для раздела “iPhone Spotlight – iOS 5,6 Settings – iOS 5-10 29 pt”:
Таблица с размерами и метками иконок для раздела “iPhone Spotlight iOS 7-10 40pt”:
Таблица с размерами и метками иконок для раздела “iPhone App iOS 7-10 60pt” (иконка нашего приложения):
Таблица с размерами и метками иконок для раздела “iPhone Notification iOS 7-10 20pt”:
Итак, приступим к созданию нашей иконки. Скачайте файл “warehouse.png” (размер 512х512) ниже на странице себе на компьютер.
Откройте любой графический редактор, которым умеете пользоваться и создайте файлы иконок в соответствии с 4 разделами, приведенными выше в таблицах. Имена файлов должны соответствовать тем, что в 4 таблицах выше.
Как пользоваться графическим редактором, рассматривать не стану. Под OS X есть бесплатный графический редактор “Gimp”, есть платный “Adobe Photoshop”.
После обработки данного файла в графическом редакторе должны получиться на выходе следующие файлы:
Отлично с этим справились, теперь необходимо перетащить из “Finder” иконки “*.png” в соответствующие места в “App Icon” по разделам. Выполните это, должно получиться вот так:
Теперь закройте проект “Warehouse” и откройте его снова. Обратите внимание на иконку приложения, которая появилась в панели инструментов.
Запустите приложение. Затем выполните комбинацию клавиш “Shift + Command + H”, чтобы выйти на рабочий стол устройства. Обратите внимание на иконку приложения “Warehouse”, она тоже изменилась.
А вот так она выглядит в диалоге поиска “Spotlight”:
Теперь разберем, как добавлять картинки в ресурсы и отображать их в элементах управления. Тренироваться будет на списке товаров.
Прилагаю список картинок, которые мы будем использовать в ресурсах.
Скачайте эти картинки, затем выделите весь список. Откройте модуль “Assets.xcassets” и перетащите из “Finder” в пустую область под “App Icon” выделенный список загруженных картинок. Должно получиться вот так:
Все бы хорошо, если бы только не нововведения для картинок, начиная с iOS 10 и Xcode 8. До iOS 10, добавляя картинки подобным образом в ресурсы, все без проблем загружалось в AppStore. Но вот начиная с iOS 10, было принято, чтобы картинки были в двух разных форматах “sRGB” и “Display P3”, предпринято это было для возможности управления насыщенностью цветов. Более подробную информацию, как к этому пришли, можно получить, изучив “WWDC 16, Session 712, Working with Wide Color, Understanding and optimizing for Wide Color Gamut Displays”.
Если использовать версию среды разработки, например, Xcode 7.3.1, то в ней с минимальной версией приложения iOS 8.0 не надо делать никаких конвертаций с картинками, все без проблем загружается в AppStore. Если же загружать без конвертации “sRGB and Display P3” со среды разработки “Xcode 8”, то на этапе валидации мы получим ошибку “Invalid Bundle. The asset catalog at '$path' can't contain 16-bit or P3 assets if the app is targeting iOS releases earlier than iOS 9.3”.
Да, с одной стороны можно было поставить минимальную версию iOS 9.3, ничего не конвертировать и отправить приложение в AppStore, но тогда бы я потерял пользователей, у кого iOS 8, 8.1, 8.2, 8.3, 9, 9.1, 9.2, 9.2.1. Пришлось разбираться, как это исправить, чтобы выполнить загрузку в AppStore, и при этом минимальная версия так и осталась iOS 8.
Для конвертации изображений в OS X есть специальная бесплатная встроенная утилита “ColorSync Utility”. Картинки, которые я показывал выше, имеют формат “RGB”, чтобы убедиться в этом. В “Finder” выполните клик правой кнопкой мыши на картинке, например, “tool001.png” и в контекстном меню выберите пункт “Get info”.
Обратите внимание на свойство “Color space”, его значение “RGB”. Создайте где-нибудь две папки с названиями “Tools_sRGB” и “Tools_Display_P3”. В эти папки мы будем складывать сконвертированные картинки.
Картинка формата “Display P3” (16 битная) будет автоматически подгружаться, если у пользователя iOS 10, если же у пользователя версия операционной системы ниже iOS 10, будет браться картинка формата “sRGB” (8 битная).
Если вы добавите только картинки в формате “sRGB”, тогда, если у пользователя операционная система iOS 10, эти картинки будут каждый раз конвертироваться из формата “sRGB” в формат “Display P3”. Добавить только картинки формата “Display P3” и не добавить картинки формата “sRGB” нельзя, надо или в обоих форматах, или только в формате “sRGB”.
Если вы обратили внимание, когда добавляли картинки в “Assets.xcassets”, а затем выделили одну из добавленных картинок, с правой стороны от нее был отображен контейнер “Universal”. Давайте включим поддержку “Display Gamut”. Выделите “tool001.png”, в панели свойств откройте вкладку “Show the attributes inspector”. Найдите свойство “Gamut”, в нем сейчас установлено значение “Any”, установите значение “sRGB and Display P3”.
Перейдите в “Finder”, теперь мы должны сконвертировать исходные загруженные картинки в два формата “sRGB” и “Display P3”. Для этого в “Finder” выделите картинку “tool001.png”, выполните по ней клик правой кнопкой мыши и в контекстном меню выберите “ColorSync Utility.app”.
В открывшемся приложении “ColorSync utility”, внизу в выпадающем списке, измените значение “Match to Profile” на “Assign Profile”. Затем нажмите на выпадающий список “None” и выберите “Display”, затем “sRGB IEC61966-2.1”.
Кнопка “Apply” станет активной, нажмите на нее, затем закройте окно ColorSync “tool001.png”, нажав на красную кнопку в правом верхнем углу окна. Вам будет предложено сохранить изменения. Сохраните изменения.
Теперь перейдите в папку “Tools_sRGB”, которую мы создавали ранее, и выделите файл “tools001.png”, нажмите на нем правой кнопкой мыши и в контекстном меню выберите пункт “Get info”.
Обратите внимание на свойство “Color profile”, оно теперь имеет то значение “sRGB IEC61966-2.1”, которое мы устанавливали через утилиту “ColorSync”.
Теперь проделайте такую же операцию, еще раз с исходным файлом изображения “tool001.png”, но на этот раз выберите “Color profile” - “Display P3”.
Нажмите кнопку “Apply” и закройте окно ColorSync “tool001.png”, сохраните изменения в папку “Tools_Display_P3”. Затем откройте “Finder”, перейдите в папку “Tools_Display_P3”, выделите файл “tool001.png”, нажмите на нем правой кнопкой мыши и в контекстном меню выберите пункт “Get info”.
Обратите внимание на свойство “Color profile”, там установлено значение “Display P3”. Теперь перейдите в Xcode, откройте модуль “Assets.xcassets”, выделите изображение “tool001” и перенесите из “Finder” картинки в контейнер. В поле “1x sRGB” перетащите картинку “tool001.png” из папки “Tools_sRGB”. В поле “1x Display P3” перетащите картинку “tool001.png” из папки “Tools_Display_P3”. Должно получиться вот так:
Остальные картинки сконвертируйте самостоятельно в форматы “sRGB” и “Display P3” по той же схеме, что мы делали выше.
Ниже вы можете скачать две сконвертированные картинки.
Также добавим в “Assets” еще картинку фона страницы авторизации.
Она имеет размер “750х1334” и называется “warehouse-view.png”. Картинку тоже необходимо сконвертировать в два формата “sRGB” и “Display P3”.
В панели навигации откройте модуль “Main.storyboard”, найдите View с именем “View Controller”, из панели компонентов перетяните на View компонент “ImageView”.
Растяните его на всю область View. Нажмите кнопку “Pin” и задайте такие ограничения:
Нажмите кнопку “Add 4 Constraints”. Измените цвет кнопки “Вход” на оранжевый, цвет текста “Нет ошибок” на белый.
Откройте модуль “SuppliesViewController.swift”. Обновите модель “supplies”, как показано ниже (заполнены свойства “productImage”):
Обновите метод “cellForRowAt indexPath”:
Тут изменения только на 92 строке, в ячейке есть встроенный компонент “ImageView”, мы обращаемся к его экземпляру и от него инициализируем свойство “image”. В инициализаторe “UIImage” мы задаем аргумент “named”, название “Image Set” из “Assets”.
Запустите приложение.
На этом мы завершаем данный урок. Большой получился урок, но тему “Assets” надо было обязательно рассмотреть, чтобы в будущем к ней уже не возвращаться.
В следующем уроке мы рассмотрим, как работать с библиотекой “Alamofire” и интегрируем ее в наше приложение. Создадим тестовый сервер, в который добавим таблицу пользователей для авторизации, а в последующих уроках переведем работу списка продуктов на сервер и перепишем клиент на интеграцию с сервером.
100+ питань з Python для Junior, Middle та Senior
Автор: Редакция ITVDN
Дорогие друзья! Предлагаем вашему вниманию перевод статьи, опубликованной на DOU.ua 30 сентября 2020 года. Оригинальная версия на украинском языке доступна по ссылке.
Редакция DOU пообщалась с разработчиками, которые проводят технические собеседования Python-специалистов для различных уровней, и собрала примерный список вопросов к кандидатам. Конечно, он не является исчерпывающим, однако содержит типичные вопросы.
Вопросы для Junior
От джуниоров требуют знать и уметь применять базовые структуры данных и модули, простейшие запросы к базам данных, знать простейшие команды системы контроля версий и тому подобное.
Общее по Computer Science и Web Development:
1. Что такое инженерия и процесс разработки в целом?
2. Какие знаете принципы программирования?
3. Чем отличаются процедурная и объектов-ориентированная парадигмы программирования?
4. Какие основные принципы ООП (наследование, инкапсуляция, полиморфизм)?
5. Что такое множественное наследование?
6. Какие есть шесть этапов разработки продукта в Software Development lifecycle и какая разница между Agile и Kanban?
7. Какие есть методы HTTP-запросов и какая между ними разница?
8. Как выглядят HTTP-request / response?
9. Что такое авторизация и как она работает?
10. Что такое cookies?
11. Что такое веб уязвимость?
12. Какие знаете классические базы данных?
13. Как читать спецификацию в конкретном языке (например, PEP8 в Python)?
14. Как происходит взаимодействие клиента и сервера?
15. Какие есть подходы к проектированию API?
16. Как использовать паттерны программирования?
17. Что такое Acceptance Testing и зачем его используют?
18. Что такое модульные и интеграционные тесты, API-тесты?
19. Как писать unit-тесты?
20. Какие есть best practices в написании автотестов?
21. Какие базовые команды системы контроля версий?
22. Как использовать Git?
23. В чем разница между хешированием и шифрованием?
Ответы на некоторые из этих вопросов вы можете найти в видео курсах Python Базовый, Python Углублённый, Основы работы с Git.
Python:
24. Python - интерпретируемый язык или компилируемый?
25. Какие есть меняющиеся и постоянные типы данных?
26. Что такое область видимости переменных?
27. Что такое introspection?
28. Разница между is и ==?
29. Разница между __init __ () и __new __ ()?
30. В чем разница между потоками и процессами?
31. Какие есть виды импорта?
32. Что такое класс, итератор, генератор?
33. Что такое метакласс, переменная цикла?
34. В чем разница между итераторами и генераторами?
35. В чем разница между staticmethod и classmethod?
36. Как работают декораторы, контекстные менеджеры?
37. Как работают dict comprehension, list comprehension и set comprehension?
38. Можно ли использовать несколько декораторов для одной функции?
39. Можно ли создать декоратор из класса?
40. Какие есть основные популярные пакеты (requests, pytest, etc)?
41. Что такое lambda-функции?
42. Что означает *args, **kwargs и как они используются?
43. Что такое exceptions, <try-except>?
44. Что такое PEP (Python Enhancement Proposal), какие из них знаете (PEP 8, PEP 484)?
45. Напишите hello-world сервис, используя один из фреймворков.
46. Какие есть типы данных и какая разница между list и tuple, зачем они?
47. Как использовать встроенные коллекции (list, set, dictionary)?
48. В чем заключается сложность доступа к элементам dict?
49. Как создается объект в Python, для чего __new__, зачем __init__?
50. Что знаете из модуля collections, какими еще built-in модулями пользовались?
51. Что такое шаблонизатор и как в нем выполнять базовые операции (объединять участки шаблона, выводить дату, выводить данные с серверной стороны)?
52. Как Python работает с HTTP-сервером?
53. Что происходит, когда создается виртуальная среда?
Ответы на некоторые из этих вопросов вы можете найти в видео курсах Python Стартовый (урок 2, урок 4-8), Python Базовый (урок 1, урок 6, урок 7, урок 9), Python Углублённый (урок 1, урок 4).
Базы данных:
54. Какие есть базовые методы работы с SQL- базой данных в Python?
55. Что такое SQL-транзакция?
56. Как сделать выборку из SQL-базы с простой агрегацией?
57. Как выглядит запрос, который выполняет JOIN между таблицами и к самим себе?
58. Как отправлять запросы в SQL-базу данных без ORM?
Ответы на некоторые из этих вопросов вы можете найти в видео курсе SQL Базовый.
Алгоритмы:
59. Что такое алгоритмы (например, Big-O notation)?
60. Какие есть базовые алгоритмы сортировки?
61. Что такое Bubble Sort и как это работает?
62. Что такое линейная сложность сортировки?
Вопросы для Middle
Если джуниору все надо подсказывать и помогать, то мидл может самостоятельно взять что-то новое и быстро его изучить и понять. У него накоплено достаточно знаний и опыта, чтобы быстро овладевать новым. Он может прийти и обсудить с опытным разработчиком, проконсультироваться, но окончательных решений не принимает.
Обычно у мидлов спрашивают:
63. Ориентируетесь ли в *nix, можете ли написать скрипты/автоматизацию для себя и коллег?
64. Что такое многопоточность?
65. Что такое архитектура веб сервисов?
66. Как работает современное нагруженное веб приложение (нарисовать и обсудить примерную архитектуру, например, Twitter или Instagram)?
67. Что нужно для сайта / сервиса среднего размера (redis \ celery \ кэш \ логирование \ метрики)?
68. Как написать, задеплоить и поддерживать (микро) сервис?
69. Как масштабировать API?
70. Як проводить Code review?
71. Что такое абстрактная фабрика, как ее реализовать и зачем ее применяют?
72. Что такое цикломатическая сложность?
Python:
73. Async Python: как работает, зачем, что под капотом?
74. Сравнить асинхронные web-фреймворки.
75. Что такое модель памяти Python?
76. Что такое SQLAlchemy (Core и ORM частей) и какие есть альтернативы?
77. Принципы работы и механизм Garbage collection, reference counting?
78. Как работает thread locals?
79. Что такое _slots_?
80. Как передаются аргументы функций в Python (by value or reference)?
81. Что такое type annotation?
82. Для чего используют нижние подчеркивания в именах классов?
83. Статические анализаторы: Flake8, Pylint, Radon.
Ответы на некоторые из этих вопросов вы можете найти в видео курсе Python Углублённый (урок 3).
Базы данных:
84. Разница между SQL и NoSQL?
85. Как оптимизировать SQL-запросы?
86. Какие есть уровни изоляции транзакций?
87. Какие есть виды индексов?
88. Точечные вопросы по выбору БД, движков БД?
89. Front-end: есть ли опыт работы с «современным» JS (Babel, Webpack, TS, ES)?
90. DevOps: работали ли с Docker-контейнерами, объяснить основные термины K8s (кластер, pod, node, deployment, service), что такое Kibana?
91. Алгоритмы: что такое временная сложность алгоритма (time complexity)?
92. Углубленные знания Linux: как зайти на внешний сервер, работать с пакетами, настроить среду и выполнять операции?
93. Специфично для Data Science: как работать с пакетами для обработки и визуализации данных (NumPy, Pandas и другие)?
Ответы на некоторые из этих вопросов вы можете найти в видео курсе SQL Базовый.
Вопросы для Senior
На собеседованиях с Senior`ами обычно мало говорят о теоретической стороне технологии, больше обсуждают конкретный опыт разработчика. Поэтому формализованных вопросов здесь нет. Однако, примером могут быть:
94. Что такое @property?
95. Каким образом можно запустить код на Python параллельно?
96. Как работать с stdlib?
97. Какие задачи решали с помощью метаклассов?
98. Что такое дескрипторы?
99. Знания других языков, кроме Python (опыт).
100. Какие технологические особенности реализации распределенных систем?
101. Какие есть низкоуровневые особенности языков и фреймворков?
102. Способы и методы управления памятью.
Бонус. Практические задания
1. Спроектировать клон Instagram. Это сервис, который понятен практически любому кандидату, даже если у него нет аккаунта. На высоком уровне он очень прост: картинки, описания, комментарии. Поэтому что-то минимальное сможет описать и джуниор. Если кандидат претендует на высшие позиции, можно бесконечно копать вглубь, касаясь API, тротлинга запросов, защиты от фрода, построения фидов пользователя и тому подобное.
2. Дано рекурсивное определение чисел Фибоначчи, надо написать функцию, которая реализует это определение.
3. Есть база данных из трех таблиц — стандартная many-to-many схема. Нужно написать запрос, который объединяет три таблицы и возвращает определенный результат.
4. Даем ТЗ какого-то полезного микросервиса (сокращалка url-ов, поиск дубликатов картинок, поиск тегов в текстах) или функции (rate limiter). Просим кандидата рассказать, как бы он его реализовал. Это дает возможность узнать, что привык использовать специалист, насколько глубоко он знает и понимает различные технологии.
5. Написать какой-то несложный декоратор (выводит аргументы функции на экран или, например, измеряет сколько времени выполнялась функция).
6. Junior`у можно предложить реализовать задачу FizzBuzz test.
7. Для Middle+ я люблю давать несложные задачки на рекурсию. Например, есть вложенный список чисел и нужно что-то на нем посчитать (скажем, найти максимум). Также, можно предложить написать аналог deepcopy для конкретной структуры данных (tree, graph).
8. Для Senior - игра «спроектировать за 5 минут...». Это может быть Google, FB, Twitter, высоконагруженный интернет-магазин, сервис поиска, продажи и бронирования билетов, сайт новостей и тому подобное. Такая задача помогает понять, как кандидат решает проблемы, ход его мыслей, умеет ли он отделять главное от второстепенного, понять, какого он типа ( «в глубину» или «в ширину»).
9. Игра «у юзера что-то не работает». На примере спроектированной системы собеседователь придумывает ошибку с «дикими симптомами», которую очень сложно понять, воспроизвести. Но нужно быстро решить проблему.
10. Задание, которое демонстрирует знание и понимание list и dict comprehensions.
Looking at the below code, write down the final values of A0, A1, ...An.
A0 = dict(zip(('a','b','c','d','e'),(1,2,3,4,5)))
A1 = range(10)
A2 = sorted([i for i in A1 if i in A0])
A3 = sorted([A0[s] for s in A0])
A4 = [i for i in A1 if i in A3]
A5 = {i:i*i for i in A1}
A6 = [[i,i*i] for i in A1]
A7 = [i if i%2 else 0 for i in A1 if 2 < i < 8]
','.join(str(j**2) for j in range(10)) – what is this object ?
11. Задача, в которой есть три функции, в них выполняются базовые операции (сортировка, фильтрация, поднесение массива к квадрату). Нужно упорядочить эти три функции в порядке возрастания времени, которое уходит на их выполнение.
Place the following functions below in order of their efficiency. They all take in a list of numbers between 0 and 1. The list can be quite long. An example input list would be [random.random () for i in range (100000)]. How would you prove that your answer is correct? - profiling?
def f1 (lIn):
l1 = sorted (lIn)
l2 = [i for i in l1 if i <0.5]
return [i * i for i in l2]
def f2 (lIn):
l1 = [i for i in lIn if i <0.5]
l2 = sorted (l1)
return [i * i for i in l2]
def f3 (lIn):
l1 = [i * i for i in lIn]
l2 = sorted (l1)
return [i for i in l1 if i <(0.5 * 0.5)]
То есть, на входе все функции имеют одинаковые данные, на выходе выдают одинаковый результат. Но из-за того, что внутри операции выполняются в разном порядке, время выполнения будет отличаться. Здесь нужно разбираться в алгоритмах и понимать, что происходит с твоими данными в процессе. Эту задачу может решить Junior, а может не решить и Middle. Казалось бы, такая мелочь, но когда мы работаем с большим количеством данных, важно, чтобы код был оптимизирован и программа выполнялась максимально быстро.
12. Простые задачи на статистику или логику. Например, определить угол между стрелками часов, которые показывают 8:40.
За подготовку материала редакция DOU выражает благодарность Михаилу Кашкину (Founder в Okumy и курсов по Python), Руслану Скире (Python Developer в CodeIT LLC), Бориславу Ларину (Python Developer в Prom.ua), Владимиру Обризану (Director в Design and Test Lab), Виктору Свирскому (Senior Developer в DataArt), Николаю Зорину (CTO в Jiji, проект Genesis), Владимиру Селюху (Team Lead в Prom.ua), Сергею Галабурде (Software Engineer в N-iX), Алексею Чуприкову (Lead Python Engineer в EPAM), Ивану Лучку (TL Data Science Specialist в Boosta), Олегу Новикову, Владимиру Щербинину, Роману Могилатову (Technical Leader в SoftServe), Вадиму Рудю, Натальи Кушнир, Андрею Лейцюсю, Роману Луцю и другим.
Перевел на русский язык Владислав Сверчков
ТОП 10 найкращих HTML редакторів
Автор: Армен Маїлян
Що таке редактор HTML?
WYSIWYG редактори
Текстові HTML редактори
Найкращі HTML редактори
Visual Studio Code
Notepad++
Sublime Text
WebStorm на базі IntelliJ
Vim
Eclipse
Atom
Adobe Dreamweaver CC
Brackets
CoffeeCup HTML редактор
HTML-Online
Висновок
Що таке редактор HTML?
Якщо спростити відповідь на поставлене запитання, HTML редактор — це програма-інструмент, яка використовується для написання основи веб-сайтів. І, незважаючи на те, що практично будь-який текстовий редактор може використовуватися для створення сайтів, це зовсім не означає, що краще використовувати звичайний текстовий редактор замість спеціально створеного інструменту розробника. Сучасні HTML редактори мають безліч вбудованих механізмів, котрі істотно спрощують роботу з сайтами. Виділення спеціальних синтаксичних конструкцій, перевірка помилок, підказка та вставка часто використовуваних елементів коду HTML, механізми автозаповнення – ці та багато інших механізмів сучасних HTML редакторів щодня полегшують роботу програмістів, верстальників та дизайнерів.
Однак редактор HTML — це зовсім не одна програма. Це група програм, кожна з яких має свій функціонал, свої особливості використання, свій набір плюсів та мінусів. Завдання такого інструменту, як HTML редактор, – зменшити витрачені вами зусилля, щоб ваш код залишався функціональним і чистим.
Які ж бувають HTML редактори? Класифікуючи їх за функціональним призначенням і можливостями, виділяють: WYSIWYG редактори і текстові редактори HTML.
WYSIWYG редактори
WYSIWYG (What You See Is What You Get) – абревіатура редакторів цього типу перекладається як «що бачиш, те й отримаєш». Інша назва таких редакторів – візуальні редактори HTML. Фактично, завдання цього типу редакторів – надати інтерфейс редагування, в якому можна відразу побачити, як виглядатиме реалізація коду на сторінці діючого сайту в браузері. Для найпростішої роботи в редакторі цього типу не потрібне знання HTML. З роботи в такому редакторі простіше стартувати користувачу-початківцю, який не має досвіду написання коду.
Такий тип редакторів часто вбудовують у веб-сайти — для спрощення налаштування зовнішнього вигляду сайту за деякими заздалегідь написаними шаблонами або для редагування контенту сайту.
Текстові HTML редактори
Власне, як зрозуміло з назви, цей тип HTML редакторів орієнтований безпосередньо на роботу з текстом (кодом). Щоб використовувати такий редактор, вам знадобляться знання як мінімум мови HTML. У процесі використання такого редактора ви не зможете постійно спостерігати готову реалізацію сторінки веб-сайту, що розробляється.
Проте застосування текстового редактора дає розробнику значно більше свободи, можливостей оптимізації коду та ін.
Найкращі HTML редактори
Ми розглянули, що таке HTML редактор і кілька прикладів того, коли той чи інший тип редакторів можуть використовуватися. Розглянемо декілька популярних продуктів для розроблення, і спробуємо визначити, який текстовий редактор більше підійде для вирішення ваших завдань.
Вибір інструменту розроблення – питання смаку. Кожен професійний розробник робить цей вибір, виходячи з власних уподобань, з того, як він працюватиме з HTML редактором. Однак є ряд редакторів коду, яким розробники віддають перевагу найчастіше.
Stack Overflow щорічно складає рейтинг інструментів розробників, що використовуються найчастіше. Розглянемо результати цього опитування серед веб-розробників за 2018 рік.
Visual Studio Code
Випущений компанією Microsoft на основі коду Atom, Visual Studio Code має частину функціоналу IDE (Integrated development environment) — інтегрованого середовища розроблення — потужної програми, що містить окрім текстового редактора коду ще ряд механізмів, які дозволяють проводити аналіз коду, запуск його та налагодження. Часто уявляють саме цей інструмент, коли говорять про те, який функціонал повинне мати IDE для веб-розроблення. У багатьох рейтингах безкоштовних HTML редакторів саме Visual Studio Code займає перше місце — розробники надають йому перевагу все частіше і частіше. Так, наприклад, за даними Stack Overflow, цей редактор у 2017 році використовували 24% веб-розробників, а у 2018 році – вже 38,7%.
Плюси Visual Studio Code
Має значну частину функціоналу IDE.
Вбудований потужний механізм автозаповнення IntelliSense.
Значна кількість розширень та доповнень.
Інтегрований з Git "з коробки".
Є вбудований налагоджувач для коду JavaScript, TypeScript, Node.js
Відкритий вихідний код додатку.
Visual Studio Code розповсюджується безкоштовно.
Мінуси Visual Studio Code
З мінусів розробники відзначають досить великий час запуску програми.
Пошук за проєктами здійснюється відносно повільно.
Notepad ++
Notepad++ – це текстовий редактор, що займає небагато місця в оперативній пам`яті комп`ютера. Він розроблений для комп'ютерів під керуванням Windows. Користувачі Linux можуть використовувати його через Wine. Notepad++, випущений ще в 2003 році, є перевіреним та усталеним інструментом багатьох розробників, будучи зручним текстовим редактором для HTML коду. Цей редактор поширюється як безкоштовне програмне забезпечення, а його репозиторій доступний у GitHub. Notepad++ підтримує сторонні плагіни.
Основні переваги Notepad++
Notepad++ є простим, невимогливим до ресурсів інструментом.
Є портативна версія.
Функціонал програми легко розширюється безліччю плагінів. За бажанням такий плагін можна створити самому.
Інтерфейс програми також легко налаштовується.
Підтримується робота з великою кількістю вкладок одночасно.
Notepad++ є на 100% безкоштовною програмою.
Недоліки Notepad++
Переважна більшість користувачів цього текстового редактора HTML коду не знаходять у ньому недоліків. Однак можна відзначити деяку мінімалістичність інтерфейсу, яка не підходить ряду користувачів.
Також можна відзначити, що цей редактор не є IDE і не містить у собі його додатковий функціонал. З цієї причини багатьом користувачам доводиться використовувати якесь середовище розробки у якості додаткового інструменту до редактора Notepad++.
Sublime Text
Ще одним прикладом чудового текстового редактора для HTML є Sublime. Ця програма постачається безкоштовно з деякими обмеженнями. Іншими словами — ви можете використовувати Sublime безкоштовно, але вам доведеться купити ліцензію, якщо ви захочете скористатися всіма функціями цього редактора.
Sublime пропонує гарну підтримку, забезпечуючи постійний вихід актуальних оновлень. Користувачі можуть додавати плагіни, створені спільнотою, або створювати власні. Для значної частини розробників використання безкоштовної версії Sublime буде цілком достатнім. Якщо вам знадобиться більше можливостей, ви зможете придбати ліцензію пізніше.
Плюси Sublime
Кросплатформенність. Sublime працює у таких операційних системах, як Windows, macOS та Linux.
Sublime є інструментом, що споживає небагато ресурсів системи, тому він її не завантажує.
Є портативна версія.
Sublime надає тисячі різних доповнень з відкритим вихідним кодом, які створені великою та активною спільнотою.
Роздільне редагування. Розробники можуть використовувати кілька моніторів та редагувати різні ділянки коду одночасно.
Недоліки Sublime
Не весь функціонал доступний користувачеві безкоштовно.
Рядом користувачів відзначається незручність роботи з менеджером плагінів.
Ряд плагінів сторонніх розробників може працювати некоректно.
WebStorm на базі IntelliJ
WebStorm – дуже зручне середовище для web розроблення. WebStorm було розроблене компанією JetBrains на основі іншого їхнього продукту IDE IntelliJ.
Плюси WebStorm
Зручне автодоповнення як коду на HTML, CSS, так і на JavaScript.
Перевірка на наявність помилок та зручне налагодження коду забезпечується за допомогою інтеграції з низкою систем відстежування помилок.
Вбудована інтеграція з такими системами керування версіями, як GitHub, Git, а також Subversion, Perforce та Mercurial.
Гнучкість налаштувань.
Досить велика кількість плагінів.
Недоліки WebStorm
Властива всім IDE повільність у роботі та вимогливість до ресурсів.
Відносно складні налаштування.
Платна IDE, що розповсюджується за передплатою.
Vim
Vim (скорочення від Vi Improved) – це потужний портативний текстовий редактор з дуже багатою історією – йому вже понад 27 років. Має багатий функціонал з можливістю глибокого налаштування програми під себе. В оригінальному вигляді працює у вікні консолі. Можна використовувати версію із графічним віконним інтерфейсом – Gvim. Варто відзначити, що багато сучасних IDE — для поліпшення процесу розробки — містять емулятор функціональності Vim.
Плюси використання Vim
Повноцінна робота в багатьох операційних системах - Windows, Linux, Amiga, Mac OS X, Unix, OpenVMS, OS/2.
Глибоке налаштування роботи редактора під себе.
Дуже низькі вимоги до ресурсів. І, відповідно, — висока швидкість роботи.
Можливість редагування або перегляду файлу на віддаленому сервері через термінал
Більше 14 000 доступних пакетів розширень.
Недоліки Vim
Один із найскладніших для вивчення інструментів розробки. Високий поріг входження вимагає від користувача значних витрат часу на запам'ятовування його особливостей, команд, плагінів тощо.
Eclipse
Використання програми Eclipse як HTML редактору часто вважається надмірним. Будучи повноцінною та багатофункціональною системою розробки, вона, ймовірно, буде надто складною для написання коду на HTML та CSS. Повноцінно свої можливості Eclipse зможе проявити при розробці складних сайтів, підв'язаних на роботу з кількома базами даних і додатковими механізмами.
Часто Eclipse використовують для роботи зі сторінками, написаними на Java, PHP, JavaScript та інших мовах програмування.
Плюси Eclipse
Повноцінна IDE з усім переліком можливостей потужного інструменту розроблення.
Кросплатформенність у роботі з Windows, macOS, Linux.
Значна кількість розширень та аддонів, які допомагають гнучко налаштовувати Eclipse під різні завдання.
Приналежність Eclipse до вільного програмного забезпечення.
Мінуси Eclipse
Складність налаштування цієї IDE.
Надмірна перевантаженість як для розроблення простих сайтів на HTML та CSS.
Велика ресурсоємність.
Atom
Атом – це порівняно новий HTML редактор. Він був випущений у 2014 році командою GitHub, і з того часу, за підтримки спільноти GitHub, значно збільшив свою популярність. Цей текстовий редактор є безкоштовним, з відкритим кодом. Цікаво, що у якості слогану для Atom використовується фраза “найбільш зламаний текстовий редактор 21 століття”, маючи на увазі, що будь-який розробник може робити свій внесок у редагування, розширення, зміну та обмін вихідним кодом програми, а також створювати власні пакети для покращення Atom.
Які можливості дає Atom
Atom є кросплатформенним додатком і працює в таких операційних системах, як Windows, macOS і Linux.
Завдяки розумному механізму автозаповнення Atom допомагає швидше писати код.
Особливість інтерфейсу Atom дозволяє розбивати інтерфейс на безліч вікон, щоб ви могли порівнювати та писати код у цих вікнах одночасно.
Atom є просунутим текстовим редактором, який отримав можливості IDE завдяки різним плагінам.
Підтримує у розробленні такі мови, як: HTML, CSS, JavaScript, Python, XML, PHP, Java, SQL, C# та багато інших.
Плюси Atom
Для Atom є велика кількість доповнень, плагінів та розширень. Відак, “з коробки” Atom поставляється з 81 вбудованим пакетом, і ви також можете додати до 7500 додаткових встановлюваних пакетів. Ви також можете розробити власний пакет.
Наявність великої кількості доповнень дозволяє гнучко налаштовувати інтерфейс редактора.
Відкритий вихідний код. Весь редактор Atom розповсюджується безкоштовно, надаючи вихідний код, доступний на GitHub.
Відмінна інтеграція з Git та GitHub.
Підтримка плагіну Teletype. Цей плагін дозволяє безпосередньо в режимі реального часу писати код спільно з іншими розробниками.
Мінуси Atom
Atom є досить «ненажерливою» програмою, забираючи на себе відносно великий обсяг оперативної пам'яті.
Підтримка тих чи інших мов визначається функціоналом плагінів, написаних різними розробниками, а не єдиною організацією.
Розглянемо ще ряд додатків, що часто застосовуються у якості HTML редакторів.
Adobe Dreamweaver CC
Програма Adobe Dreamweaver CC, розроблена та керована технологічним гігантом Adobe Inc., є потужним та універсальним інструментом преміум-класу. Вона обслуговує як back-end, так і front-end розроблення. Як програмне забезпечення із закритим вихідним кодом, Dreamweaver призначений для роботи в екосистемі Adobe. Adobe також надає підтримку, плагіни та функції, щоб ви завжди могли без проблем писати код.
Dreamweaver — це один із редакторів, які підтримують як текстові, так і WYSIWYG методи роботи з кодом. Багато користувачів цієї програми вважають Dreamweaver найкращим візуальним редактором коду. Таким чином, ви можете вибирати, чи ви хочете працювати з візуальним поданням сторінки або йти класичним шляхом редагування тексту.
Основні переваги Dreamweaver CC.
Dreamweaver дозволяє писати код будь-якою з основних мов програмування.
Підтримує текстові та WYSIWYG режими редактора.
Зручний перегляд. Можливість побачити, як виглядає тег, виділивши його.
Повністю інтегрований із програмною екосистемою Adobe.
Приголомшлива продуктивність.
Підтримка Adobe Inc.
Підписка на Dreamweaver дає доступ до ряду хмарних бібліотек, що містять величезний обсяг графіки, стилів, шарів та багато іншого.
Недоліки Adobe Dreamweaver CC
Основним недоліком цього редактора є ціна та умови розповсюдження. Як і інші продукти компанії Adobe, Dreamweaver CC поширюється лише за умови передплати.
Brackets
Brackets — це програмний продукт Adobe, розроблений спеціально для дизайнерів та фронтенд розробників, котрий побачив світ у 2012 році. Цей молодий текстовий редактор, що розповсюджується, на відміну від Dreamweaver, безкоштовно, не може похвалитися великим вибором плагінів, проте відмінно працює з HTML, CSS і JavaScript – основними мовами фронтенд-розробника.
Плюси Brackets
Зв'язок із Google Chrome. Основна особливість редактора Brackets, що виділяється багатьма розробниками, — зв'язок із Google Chrome у режимі реального часу. За допомогою цього механізму розробник може відразу після внесеної зміни спостерігати, як усі ці зміни відображатимуться в браузері.
Доступність на Windows, macOS, Linux.
Brackets визнаний одним із найкращих текстових редакторів під macOS.
Широко розвинена система гарячих клавіш.
Основною особливістю, яка відрізняє Brackets від інших HTML-редакторів, є функція «Вилучити». Функція вилучення дозволяє витягувати інформацію прямо з PSD — таку як шрифти, кольори та вимірювання, з чистим CSS та без контекстних посилань на код.
Мінуси Brackets
Невелика кількість розширень порівняно з іншими редакторами на ринку.
Відсутність підтримки серверних мов (Python, PHP, Ruby).
CoffeeCup HTML редактор
HTML редактор CoffeeCup представлений на ринку як безкоштовною, так і платною версією. Незважаючи на слабку поширеність у російськомовному сегменті Інтернету, HTML редактор CoffeeCup досить популярний за кордоном. Випущений вперше ще 1996 року, до 2008 року редактор було продано вже числом 30 млн. копій.
Плюси CoffeeCup
У платній версії є окрім текстового ще й WYSIWYG-редактор.
CoffeeCup повністю сумісний із платформами Windows та macOS.
Платна версія HTML-редактора CoffeeCup включає в себе бібліотеку тегів, перевірку HTML і CSS, завершення ймовірного коду тощо.
Зручне автозаповнення тегів.
Недоліки CoffeeCup
Значна частина функціоналу та матеріалів бібліотеки представлена лише у платній версії.
HTML-Online
Завершимо наш огляд популярних HTML редакторів зручним інструментом для створення та редагування коду прямо в браузері — HTML-Online. HTML-Online є простим та зручним редактором веб-сторінок. Він, ймовірно, один з найкращих візуальних HTML редакторів серед онлайн сервісів. Завдяки сервісу HTML-Online ви зможете почати писати коди вашого нового сайту прямо в браузері, без необхідності завантажувати та встановлювати відповідну програму.
Переваги HTML-Online
Є як текстовим, так і візуальним редактором, дозволяючи спостерігати за результатами написання у процесі розробки.
Зручна конвертація файлів із формату документів Word у HTML, що дозволяє відразу застосовувати правила HTML розмітки до матеріалів із Word-івських файлів. Вбудована підтримка роботи з документами Excel, PDF та іншими форматами.
Простий графічний редактор HTML.
Недоліки HTML-Online
Основним недоліком онлайн текстових редакторів взагалі і HTML-Online зокрема є необхідність писати код відразу. Якщо ви не напишете проєкт за раз, або у вас перерветься інтернет-з'єднання, то доведеться робити проєкт спочатку.
Функціонал онлайн редакторів виглядає бліднішим на тлі можливостей повноцінних додатків.
Висновок
У кожного практикуючого розробника є можливість самому вибрати для себе відповідний інструмент-редактор зі своїм функціоналом «з коробки» та доступними плагінами.
Ми розглянули ряд редакторів, визнаних більшістю розробників найкращими HTML редакторами. Чи зможемо вибрати серед них найкращий редактор веб-сторінок? На жаль, ні.
Як видно, для полегшення роботи фронтенд розробника існує безліч різноманітних додатків, що відрізняються як вбудованим функціоналом та дизайном, доступом до плагінів та додаткових бібліотек, так і порогом входження та доступними платформами, на яких працюють редактори. Ці різноманітні додатки – лише інструменти в руках людини, котрі застосовуються, виходячи з конкретного завдання й особистих смаків.
Не так важливо, щоб ви одразу обрали для себе один раз і назавжди зручний текстовий редактор для HTML, як важливо, щоб Ви продовжували писати нові сайти, вчилися новим технологіям та відкривали для себе нові інструменти без припинення навчання.
Project Manager в IT компанії
Автор: Редакция ITVDN
В ноябре 2016 года на ITVDN появятся первые видео курсы по управлению проектами. Дмитрий Охрименко, CEO ITVDN, встретился с Еленой Петровой, новым бизнес-партнером ITVDN и автором курсов по Project Management, чтобы обсудить вопросы, которые интересуют пользователей нашего образовательного ресурса.
Дмитрий: Елена, пользователи ITVDN - в основном программисты. Расскажи, пожалуйста, в чем суть Проектного Управления и чем новый курс будет полезен для разработчика?
Елена: Как ты знаешь, разработчики работают в команде, которой управляет Project Manager. Если нет PM` a, то есть Team Lead, и в этом случае он - менеджер, который организовывает процесс работы. Разработчику нужно понимать, почему от него что-то требуют, ведь бытует мнение, что работа разработчика — это творчество, а на самом деле это не совсем так, есть ограничения. Есть ограничения по требованиям, по каким-то условиям в компании, в зависимости от модели бизнеса. Например, в той компании, в которой работает разработчик, она диктует определенные правила работы. Опять же, в зависимости от того, какая организационная структура - матричная, проектная или функциональная - это все очень влияет на его полномочия.
Дмитрий: Надеюсь, это есть в курсе?
Елена: Конечно, в курсе есть и это, также в курсе мы подробно рассматриваем состав команды. Кстати, это тоже очень полезно для разработчиков - знать, с кем он работает и какие обязанности у других людей. Мы рассматриваем бизнес аналитика, какие у него задачи и возможности, какие задачи и обязанности у sales manager. Достаточно часто бывает такое, что у разработчиков, у всей команды вцелом, включая PM`a, есть определенное недовольство sales`ами.
Дмитрий: Обязательно кто-то должен быть виноват во всем.
Елена: Да, продали то, что нереализуемо или еще что-то. В таком случае мы пытаемся в этом курсе показать, что у всех есть определенные интересы, но успех бизнеса будет только в том случае, если они согласуют между собой все эти интересы и построят такой процесс, когда кому-то придётся чем-то пожертвовать для общего блага компании.
Дмитрий: На основе какой методологии управления проектом будет построен курс? Какая это методология?
Елена: Я бы могла сказать, что курс построен на PMBoK, но на самом деле нет. PMBoK- это обо всем, это идеальный вариант, сбор лучших практик со всего мира с разных проектов, но далеко не все это применимо в жизни. Каждый PM должен знать, что требует PMBoK, это никогда не помешает и только разнообразит его методы управления. Но применять в жизни он должен очень выборочно и очень осторожно. Далеко не всегда то, что применимо в NASA, применимо для компании, которая занимается e-commerce.
Дмитрий: По Вашему мнению, что самое сложное в работе PM`a? Самое интересное и самое сложное?
Елена: Как ни странно, PM - это посредник, даже больший посредник чем sales. И ему нужно быть очень гибким, ему нужно понимать комбинации различных интересов. Самое важное и сложное то, с чем многие PM`ы "факапят", когда они становятся на сторону команды, но на самом деле PM выражает интересы бизнеса, не заказчика, не команды. Он - наемный работник, он работает на бизнес, его задача, чтобы клиент был доволен, но и при этом бизнес не пострадал. Есть разные способы не навредить и получить выгоду, об этом я тоже буду говорить в курсе, но самое важное здесь - правильно выбрать позицию. Ни в коем случае ни перед кем не очернять заказчика или компанию. PM очень часто overtime-ит, потому что он пытается объять необъятное. Нужно сконцентрироваться на общих интересах для проекта, удовлетворить каждого разработчика все равно не получится. Он должен занять очень умеренную позицию – это сложно, но интересно. Я бы сказала, что для PM`a очень важен склад характера, когда он готов рассматривать различные решения той или иной проблемы и принимать комплексное решение. Как говорят, успех проекта - это в срок, в рамках бюджета и объема работ, также это успех и для PM`a. Но, на самом деле ,это не совсем так. Самое важное - это получить выгоду и не растерять команду. То, о чем мы говорили: на чью сторону должен стать PM, если есть конфликт между заказчиком и командой. Становиться на чью-то сторону нельзя. Нужно правильно уметь объяснить команде, почему то или иное решение было принято.
Дмитрий: PM должен преподнести так проблему, чтобы и команда осталась в плюсе, и проект принес то, что бизнес изначально планировал получить. Из Вашего опыта, например, разработчики общаются с тестировщиками. Тестировщик - это отдельный типаж работников в ИТ компании, а разработчик — это другой типаж. У каждого есть свои особенности и фишки. Что самое сложное в общении между PM и разработчиком? И есть ли вообще такие сложности?
Елена: Сложности в общении зависят только от человека. Если он готов идти на компромиссы и заинтересован в результате, то всё решаемо. На мой взгляд, есть более серьезные проблемы. Когда разработчик не понимает, что нужно сделать. Он хочет что-то сделать и делает это хорошо, но со своей точки зрения. Из-за этого бывают конфликты, причем зачастую между разработчиком и бизнес-аналитиком, если такой, конечно, есть. В маленьких компаниях обычно все функции бизнес-аналитика выполняет PM или Team Lead разработчик. Если не было уделено достаточно внимания проработке бизнес-потребности заказчика, то разработки могут быть потом и не применимы в жизни.
Дмитрий: То есть, проблема обычно в непонимании предметной области?
Елена: Я бы не сказала, что это так. Скорее, это непонимание потребности заказчика. Ведь у него есть свои ограничения, свои требования по внешним условиям. У нас был как-то случай. Проект нужно сделать к определенному сроку. Начинается футбольный сезон и все – должен быть запущен продукт. Тут были ограничения по скоулпу и по функционалу, который действительно нужен. Ведь заказчик не всегда понимает, что ему нужно. Он дает материал, но после анализа команда понимает, что нужно ограничиться и делать только необходимое. Тут как раз и начинается работа и PM, и бизнес-аналитика, и команды разработчиков, поскольку чрезмерное увлечение архитектурой, например, или «как было бы хорошо сделать» не всегда работает. При этом, упрощая, нужно правильно масштабировать проект, чтобы впоследствии можно было бы как-то дорабатывать продукт.
Дмитрий: Еще вопрос. У меня есть много знакомых, которые работают PM, и они регулярно пытаются изучать программирование на C#, JS, Java. Вот насколько это вообще нужно PM? Правильно ли это – пытаться понять работу разработчика, влезать в нее, помогать?
Елена: Думаю, они должны знать, что такое объектно-ориентированное программирование, должны знать основные технологии. На мой взгляд, достаточно понимать, в какой предметной области ты работаешь, какого типа продукт ты создаешь и какие технологии сейчас применимы к разработке подобных продуктов. Если PM будет нырять глубже, это будет только мешать. Точно так же и разработчики – я рекомендую только первый курс «Введение в PM», это даст им понимание, в какой среде они работают, почему именно так устроена компания, почему именно такие решения принимает менеджер или руководитель компании. Разработчикам желательно знать и понимать такие вещи, от этого будет зависеть успешность их работы.
Дмитрий: Насколько реалистична ситуация, когда разработчик становиться PM? Например, некоторые наши студенты на вопросы «Кем хотите быть?», «Как Вы видите свое дальнейшее развитие?» кто-то отвечает, что через какое-то время хочет стать Team Lead/Senior Developer, кто-то хочет стать PM. Насколько такой процесс развития разработчиков реалистичен?
Елена: Все вполне реально. Есть замечательные PM – выходцы из разработчиков. Но тенденция такова, что лучше разработчику стать Product менеджером, тем более, что сейчас активно стараются создать тенденцию развития продуктового бизнеса. И разработчику с опытом и навыками, которыми он владеет, с его отношением к работе, более интересно будет управлять продуктом. Разработчику ,скорее, нужно больше знаний в бизнес-анализе и в управлении людьми. Например, управление расписанием, рисками и т.д.
Дмитрий: А кто будет идеальным PM? Какой портрет человека? Чем он должен заниматься?
Елена: Лично мое мнение из того, с чем я сталкивалась, такое, что идеальные PM выходят из QA специалистов. Вот, действительно, очень хороши. Говорят, что девушки - лучшие PM, нежели мужчины. Тут можно поспорить. Лишь до определенной степени это правда. У девушек слишком живой ум, они впечатлительнее мужчин, а PM должен четко понимать границы проекта, границы компании. И какие бы эмоции или мысли не возникали, хороший PM всегда должен придерживаться этих рамок. Я знаю отличных PM и девушек, и парней, и разработчиков, и даже тех, кто не связан с IT. Сейчас многие идут в IT на PM, ведь программирование для этого учить не нужно. Не всегда в таком сценарии все получается, но бывают и удачные случаи.
Дмитрий: Ты сказала, что программисту лучше расти в сторону Product менеджмента. В чем кардинальные отличия между продуктовыми компаниями и аутсорсинговыми, с точки зрения PM?
Елена: В продуктовой компании главный Product менеджер.
Дмитрий: PМ там не нужен?
Елена: Нет, PМ там нужен, обязательно. Product менеджер разрабатывает стратегию развития продукта, а какие-то элементы или дополнения к продукту идут как проекты. Вот ими, обычно, и занимается PМ, подчиняясь Product менеджеру. В продуктовых компаниях заказчиком является Product менеджер, в то время как в аутсорсинговых компаниях заказчик вне бизнеса. Поэтому в аутсорсе приходиться комбинировать интересы внешнего заказчика и внутреннего бизнеса. В продуктовых компаниях, на мой взгляд, у PМ меньше ответственности: он принимает меньше решений, у него меньше посредничества.
Дмитрий: Он просто управляет отдельными маленькими проектами, которые нужны для общего развития продукта?
Елена: Да, верно. У PМ в продуктовых компаниях вполне определенные организационные функции – это скучнее, но безопаснее, чем в аутсорсе. Зато есть четкие задачи, четкое понимание продукта, ситуации, связей. А ответственность за идею и главную цель несет Рroduct менеджер. В аутсорсинговых компаниях нет как такового Product менеджера, а РМ приходиться постоянно лавировать. Работа более изматывающая, но некоторые находят это более живым и интересным.
Дмитрий: Чтобы стать Product менеджером, какие знания и навыки нужно культивировать? Что читать и где учиться?
Елена: Сейчас есть очень много информации для Product менеджеров. И вебинаров хватает на тему «Кто такой Product менеджер?», и курсы появляются. На мой взгляд, вне зависимости от того, разработчик ты, тестировщик или еще кто-то, чтобы стать Product менеджером, необходимо пройти через бизнес-аналитика. Нужно получить навыки бизнес-аналитика, поскольку даже в аутсорсинговой компании главный человек, который работает с продуктом – это аналитик. Хороший специалист изучает бизнес заказчика, рынок, конкурентов, продукт, он должен понимать, какие "фичи" этого продукта будут эффективными с точки зрения экономической эффективности. И это первый шаг для того, чтобы стать Product менеджером.
Дмитрий: Какой второй?
Елена: У Product менеджера еще больше функций, помимо аналитики. Он является, в первую очередь, носителем идеи самого продукта, «гореть» самой идеей данного продукта. Также Product менеджер должен понимать, какие бизнес-потребности не только своих пользователей он решает, но и свои - почему он выгоден. Почему вообще владелец бизнеса спонсирует производство этого продукта? Product менеджер – это смесь технической роли, аналитики и серьезного понимания бизнеса. Так что, если разработчик не планирует идти вглубь технологий, а заняться карьерным ростом, то сначала это бизнес-аналитика, потом Product менеджер, ну а там уже много вариантов. Многие создают свои компании, именно пройдя такой путь.
Дмитрий: Они получают понимание бизнеса, видят, как работает сама «кухня».
Елена: Да. Сейчас очень много компаний, где руководители – это бывшие разработчики. Но им не хватает именно понимания того, как организовать работу, процесс.
Дмитрий: Думаю, нашим студентам будет полезна эта информация про РМ и Product менеджера.
Елена: Надеюсь. Я записывала курс «Введение в РМ» не столько, как курс по Product менеджменту, это курс по менеджменту в IT компании. Как я говорила, он будет полезен любому человеку, который работает с командами. Это может быть Team Lead или HR. HR-ам и рекрутерам это будет мега-полезно, потому что они занимаются поиском и подбором персонала и им нужно задавать правильные вопросы, уметь правильно оценить резюме. А также будет полезно sales’ам, они не всегда понимают, как работает операционная сторона. Если они прослушают курс, то поймут, чем занимается РМ, по каким вопросам с ним можно консультироваться.
Дмитрий: Кто больше всего критикует работу PМ?
Елена: Разработчики. Они говорят, что РМ не нужны, они мешают работать. Я частично с этим мнением согласна, но ведь одна из задач РМ – это устранять проблемы для разработчиков. А задача разработчиков – взаимодействовать, участвовать в организации процесса работы. От них требуется помощь РМ, потому что он не всегда может обосновать, почему то или иное решение приняла команда. И опять же, если в проекте идет что-то не так, в этом виноват не один только РМ, в этом виновата вся команда.
Дмитрий: Но РМ в первую очередь, потому что…
Елена: Да, потому что не смог организовать команду, чтобы она вместе предотвратила эту проблему. Я очень рада, что записываю данный курс, потому что в нем смогу отразить свой опыт работы в процессном менеджменте. Я отлично видела роли и их взаимодействие на уровне продукта, организации, компании и т.д.
Дмитрий: Какого опыта у тебя больше? С чем больше работала?
Елена: Я, на самом деле, процессный аналитик. Мое основное достижение – это руководство процессом оценивания компаний по модели CMMI. Это модель управления процессами в компании, она охватывает как инженерные процессы, самые простые, так и процессы управления проектами, управления организации и поддержки (системные администраторы и т.д.).
Любой человек, который занимается организацией рабочих процессов, знает, что есть такой инструмент, как теория ограничений, она показывает, где в цепочке производства компании самые узкие места, и проблема обычно на стыке разных специальностей, на стыке разных профессий, разных отделов.
Асинхронне програмування на JavaScript
Автор: Дмитро Охріменко
План:
1. Різниця між синхронним та асинхронним кодом
2. Багатозадачність процеси й потоки, у чому різниця
3. Особливості багатозадачності в JavaScript
4. Асинхронні операції на практиці HTTP-запит як найпоширеніший кейс
5. Підходи до написання асинхронного коду:
Promise
Async/Await
Observable
6. Практичні поради
Різниця між синхронним та асинхронним кодом
Для початку давайте визначимо ці два терміни:
Синхронний код - це код, який виконується послідовно, функція за функцією.
Асинхронний код - код, який може виконуватися паралельно: наступна функція запускається, не чекаючи завершення попередньої.
Щоб провести аналогію з реального життя, уявімо кухаря. Якщо кухар працює синхронно, то поки він не завершить приготування однієї страви, не переходить до наступної. Але це неефективно й призводить до втрати часу. Якщо ж кухар діє асинхронно, то поки м’ясо запікається в духовці, а на плиті закипає вода, він нарізає овочі. Тобто він один, але не стоїть без діла - виконує інші задачі, поки щось готується саме.
Уявімо, що кухар - це процесор. А запікання м’яса в духовці - це завантаження файлу з мережі. Кухар може просто стояти й дивитись, як м’ясо готується. А може нарізати овочі, перевіряти, чи не з’явились нові замовлення, або скролити стрічку в соцмережі. Так само і з програмами: поки мережева карта завантажує файл, процесор не мусить чекати - він може малювати інтерфейс, оновлювати прогрес-бар чи виконувати обчислення у фоні. Але для цього потрібно правильно написати код - так, щоб він міг працювати асинхронно.
Код який виконується синхронно
```js
console.log("Початок");
console.log("Дія");
сonsole.log("Кінець");
```
Результат:
Початок
Дія
Кінець
Код який виконується асинхронно. і
``js
console.log("Початок");
setTimeout(() => { // за допомогою setTimeout ми відкладаємо запуск коду на певний час
console.log("Дія через 2 секунди");
}, 2000);
сonsole.log("Кінець");
```
Результат:
Початок
Кінець
Дія через 2 секунди
Це не та багатозадачність, як у деяких інших мовах програмування. Тут не використовуються додаткові потоки, а все працює завдяки механізму подій. Але про це детальніше дал
Багатозадачність: процеси й потоки, у чому різниця
Багатозадачність в операційній системі - це можливість запускати та керувати кількома задачами одночасно. Наприклад, працювати в браузері, слухати музику, завантажувати файл і паралельно редагувати код у Visual Studio.
На практиці процесор дуже швидко перемикається між усіма цими задачами, створюючи ілюзію одночасного виконання. Якщо процесор багатоядерний - деякі задачі справді можуть виконуватись паралельно.
Багатозадачність тісно пов'язана з двома важливими поняттями - процесами та потоками.
Процес (process) - це окремий екземпляр програми у пам'яті, який має власні ресурси: виділену область оперативної пам'яті, дескриптори файлів, змінні оточення тощо.
Потік (thread) - це одиниця виконання всередині процесу. Потоки одного процесу працюють незалежно, але мають спільний доступ до пам'яті та ресурсів процесу.
Процеси дозволяють запускати різні програми одночасно - наприклад, Google Chrome, Visual Studio Code і т.д.
Потоки дають змогу виконувати кілька задач усередині однієї програми. Наприклад, у Visual Studio Code один потік відповідає за оновлення інтерфейсу, інший перевіряє помилки в коді, ще один формує підказки під час написання. Це, звісно, спрощений приклад - у реальності VS Code використовує ще й окремі процеси для розширень і мовних серверів.
Операційна система керує як процесами, так і потоками. Вона розподіляє процесорний час між ними, ставить у чергу, може призупиняти виконання або відновлювати його за потреби.
Давайте трохи адаптуємо наш приклад з кухарем із попереднього посту. Уявімо, що процес - це ресторан, а потік - це кухар. Ресторан має все необхідне для приготування їжі: кухонне приладдя, продукти, рецепти (це можна розглядати як пам’ять і доступ до інших ресурсів). Кухар читає рецепт і, використовуючи ресурси ресторану, готує страву - так само, як потік виконує інструкції нашої програми, використовуючи ресурси процесу. Якщо ресторан хоче готувати кілька страв одночасно, йому потрібно більше кухарів, які працюють паралельно на одній кухні. Аналогічно, якщо програма повинна виконувати кілька задач одночасно - завантажувати файли, обробляти введення, оновлювати інтерфейс - вона може використовувати кілька потоків.
Коли ми створюємо програму і хочемо зробити її зручною для користувача, а також ефективною з точки зору використання ресурсів, які виділяє операційна система на процес, ми іноді починаємо використовувати потоки та прийоми багатопотокового програмування. Це велика окрема тема, і ми її зараз чіпати не будемо. Одна з причин - у JavaScript немає прямого доступу до потоків.
Уточнення. Якщо ви хочете використовувати JavaScript і все ж таки працювати з потоками - у вас є Web Workers:
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
А якщо JavaScript виконується не в браузері (наприклад, у Node.js), тоді можна використовувати модуль `worker_threads`. Але варто розуміти, що це не частина стандарту мови, а можливість середовища виконання.
Додаткові корисні ресурси по цій темі:
https://www.youtube.com/@CoreDumpped - канал з короткими відео про те як працює комп'ютер.
Modern Operating System by Andrew Tanenbaum - принцип побудови та роботи операційних систем (може бути викликом для новачка, але нормально як для технічної книжки)
Особливості багатозадачності в JavaScript
JavaScript працює в одному потоці - це означає, що в будь-який момент часу виконується лише один фрагмент коду. Увесь код, який ми пишемо, виконується у call stack: це структура, в яку потрапляють усі функції, що викликаються.
Якщо одна з функцій виконується довго (наприклад, важке обчислення), усі інші задачі - включно з обробкою кліків, рендерингом чи відповідями від сервера - будуть чекати, поки call stack не звільниться.
Щоб не блокувати цей єдиний потік, браузер надає асинхронні API (setTimeout, fetch, Web API). Коли ми викликаємо, скажімо, fetch(), у стек додається лише короткий виклик цієї функції. Власне мережевий запит виконується в окремому потоці, який створює браузер. Тобто, один потік виконує задачі які є у call stack, а інший потік чекає поки відповідь поверне сервер.
Але асинхронна операція колись завершиться і треба механізм який віддасть нашому головному потоку результат роботи іншого потоку. Коли це стається колбек або проміс‑резолвер не додається одразу у call stack. Спершу він потрапляє до черги подій (task queue). За роботою черги стежить event loop. Його правило просте - поки стек порожній дістати першу задачу із черги і покласти у стек.
Так ми досягаємо псевдобагатозадачності: основний потік виконує короткі шматки коду послідовно, а довгі операції «живуть» поза стеком. Коли довгі операції завершуються вони формують чергу задач, які треба виконати а event loop ці задачі закидає до стеку, коли call stack стає порожнім.
Це максимально спрощене пояснення, і без візуалізації може здатися складним. Якщо хочете краще зрозуміти, дуже раджу подивитись відео Jake Archibald — "In The Loop" на YouTube (англійською). https://www.youtube.com/watch?v=8aGhZQkoFbQ
Або приходьте на мій курс JavaScript Поглиблений, де ми розбираємо це на практиці.
Також корисна стаття на MDN, де ці процеси описані докладніше.
Асинхронні операції на практиці: HTTP-запит як найпоширеніший кейс
Один з прикладів асинхронної операції - це запит на сервер через HTTP-протокол. Якщо організовувати запит через JavaScript у браузері без використання React, Angular або Vue.js, то це можна зробити за допомогою:
fetch
XMLHttpRequest
Спеціалізована бібліотека, наприклад, Axios
Ось так буде виглядати простий код написаний на fetch
```js
fetch('https://jsonplaceholder.typicode.com/users')
.then(res => res.json())
.then(data => console.log(data));
```
А так на axios (axios одразу повертає розпарсений JSON як response.data, на відміну від fetch, де потрібно викликати .json() вручну)
```js
axios.get('https://jsonplaceholder.typicode.com/users')
.then(response => console.log(response.data));
```
Якщо розглянути саме fetch то ось що відбулося під капотом:
fetch створює HTTP запит вказавши HTTP метод, заголовки, тіло тощо
Цей запит передається у вбудовану систему Web API - окрему від JavaScript середу, яка працює в іншому потоці.
JavaScript не чекає відповіді - основний потік продовжує виконувати інший код
fetch повертає Promise - об'єкт, що представляє асинхронну операцію, результат якої з’явиться пізніше
Коли відповідь від сервера приходить, Web API кладе callback в чергу.
Event Loop перевіряє, чи call stack порожній, і виконує цю мікрозадачу.
Така поведінка дозволяє браузеру одночасно виконувати інші задачі, не чекаючи завершення запиту.
Про використання асинхронного коду в JavaScript є [безкоштовний урок на YouTube](https://www.youtube.com/watch?v=cvR1EQ1R0EQ)
Також більше про синтаксис Promise можна дізнатися в уроці [Асинхронний код. Promise](https://itvdn.com/ua/video/javascript-essential-ua/js-promise-ua) на ITVDN, а детальніше про варіанти організації такого коду буде написано далі.
Підходи до написання асинхронного коду
Складність роботи з асинхронним кодом полягає в тому, що обробка результату операції відбувається не відразу, а через певний час після її запуску. Ми ініціюємо асинхронну операцію й можемо виконувати інші завдання, але все одно маємо якось дізнатися про її завершення та обробити результат. Проблема в тому, що в цей момент програма вже виконує інші дії.
Тому для обробки асинхронних операцій використовується push-модель взаємодії: отримувача даних (наш код) викликає провайдер даних - окремий механізм, який керує асинхронною операцією. По суті, розробнику потрібно відреагувати на подію завершення асинхронної операції. Для цього існує кілька підходів:
callback-функція
Promise
async/await (синтаксичний цукор над Promise)
Observables
Використання функцій зворотнього виклику (callback)
Почнемо з callback-функцій. Це найпростіший підхід, але він може призвести до заплутаного коду, особливо коли одна асинхронна операція запускає іншу, і так утворюється ланцюг.
Уявімо, що маємо функцію downloadImage(url, callback), яка завантажує зображення асинхронно, не блокуючи основний потік. Перший параметр - це адреса зображення, яке потрібно завантажити, а другий - функція, яку буде викликано після завершення завантаження. При цьому саме зображення буде передане як параметр у callback.
Приклад використання:
```js
downloadImage(url1, image => document.body.append(image))
```
На перший погляд усе просто. Але якщо потрібно завантажити кілька зображень послідовно, код стає менш зрозумілим:
```js
downloadImage(url1, image => {
document.body.append(image);
downloadImage(url2, image => {
document.body.append(image);
downloadImage(url3, image => {
document.body.append(image);
})
})
});
```
Така вкладена структура швидко ускладнюється, особливо якщо замість одного рядка з DOM-змінами з’являється додаткова логіка. Подібний стиль називають "Pyramid of Doom", і його краще уникати.
Один зі способів спростити обробку асинхронних викликів - це використання Promise.
Використання Promise
Promise - це об’єкт, який представляє асинхронну операцію. У перекладі з англійської promise означає «обіцянка». Можна уявити, що це обіцянка від браузера надати в майбутньому або результат операції, або помилку, пов’язану з її виконанням.
Приклад використання: перепишемо попередню функцію downloadImage, щоб вона повертала Promise.
```js
let promise = downloadImage(url1);
promise.then(image => document.body.append(image));
```
Тут ми все одно використовуємо callback-функцію, але передаємо її вже в метод .then() об’єкта promise. Це важливий момент:
тепер асинхронна операція має об’єктне представлення, яке можна передавати як параметр у різні частини коду;
можна будувати ланцюжки промісів, позбуваючись вкладеності, яка виникала з callback.
Приклад:
```js
downloadImage(url1) // отримуємо проміс
.then(image => { // вказуємо що робити коли promise перейде в стан resolved
document.body.append(image);
return downloadImage(url2); // виконуємо метод, який повертає promise
})
.then(image => { // результат роботи попереднього промісу передається як значення
document.body.append(image);
return downloadImage(url3);
})
.then(image => {
document.body.append(image);
});
```
Тепер код виглядає лінійним і набагато зручнішим для супроводу.
У прикладах вище ми не розглядали, як саме створюється Promise, адже важливо зрозуміти мотивацію використання цих об’єктів. Тим більше, що більшість API браузера вже повертають готові проміси. Наприклад:
```js
fetch('<https://jsonplaceholder.typicode.com/users>')
.then(res => res.json());
```
Якщо хочете детальніше розібратися зі створенням Promise вручну - перегляньте документацію на MDN або мій відео урок на ITVDN.
Async/await
Супроводжувати синхронний код завжди простіше, ніж асинхронний. У 2012 році в мові C# з’явився синтаксичний цукор, який значно спростив роботу з асинхронними операціями: замість вкладених callback можна було використовувати послідовний синтаксис з новими ключовими словами async та await. Згодом цю концепцію перейняли й інші мови програмування, зокрема Python та JavaScript. В JavaScript підтримку async/await додали у 2017 році.
Призначення ключових слів
async - додається до функції та вказує, що вона завжди повертає Promise.
await - використовується перед об’єктом-промісом, щоб "дочекатися" результату перед виконанням наступних рядків коду.
Перепишемо попередній приклад із завантаженням зображень, використовуючи async/await:
```js
let image = null;
image = await downloadImage(url1);
document.body.append(image);
image = await downloadImage(url2);
document.body.append(image);
image = await downloadImage(url3);
document.body.append(image);
```
Тепер код виглядає як звичайний синхронний: немає вкладених callback, усе читається рядок за рядком. Можна подумати, що await "зупиняє" виконання, очікуючи на результат промісу. Насправді ж код не блокує основний потік - під капотом він перетворюється на машину станів, де кожен стан описує дію до або після await.
Ще одна перевага async/await - знайомий синтаксис для обробки помилок:
```js
try {
let image = null;
image = await downloadImage(url1);
document.body.append(image);
image = await downloadImage(url2);
document.body.append(image);
image = await downloadImage(url3);
document.body.append(image);
} catch (ex) {
// обробка помилки
}
```
У результаті асинхронний код виглядає так само зрозуміло, як і синхронний, що значно спрощує його супровід.
Observable
Observable - це ще один підхід до організації асинхронного коду. Назва походить від однойменного патерна проєктування (Observer pattern), який описує створення об’єктів, за якими можна «спостерігати», отримуючи від них сповіщення. Тобто це реалізація подієвої моделі за допомогою ООП.
У сучасному JavaScript ця ідея пішла далі й стала основою реактивного програмування та бібліотеки RxJS.
Якщо Promise представляє одне майбутнє значення (успішне або помилкове), то Observable - це потік значень, які можуть з’являтися з часом.
Можна уявити:
Promise - це одна посилка, яку ви отримаєте в майбутньому;
Observable - це підписка на журнал, нові випуски якого надходитимуть регулярно.
Щоб створити Observable, використовують конструктор або готові оператори RxJS. Наприклад, функція downloadImages(urls) може завантажувати кілька картинок і відправляти їх «у потік» по мірі завантаження:
```js
import { Observable } from 'rxjs';
function downloadImages(urls) {
return new Observable(subscriber => {
urls.forEach(url => {
downloadImage(url, image => {
subscriber.next(image); // надсилаємо картинку у потік
});
});
subscriber.complete(); // повідомляємо, що потік завершено
});
}
```
Щоб використати Observable, на нього треба підписатися за допомогою subscribe:
```js
downloadImages([url1, url2, url3])
.subscribe({
next: image => document.body.append(image), // що робити з новим значенням
error: err => console.error(err), // обробка помилок
});
```
Переваги Observable
працюють із потоком даних, а не з одним результатом;
підтримують підключення операторів трансформації (фільтрація, мапінг, комбінування потоків);
можна легко скасувати виконання (відписатися від потоку).
Нижче приклад обробки даних через оператори. В RxJS оператори підключаються через метод pipe:
```js
import { filter, map } from 'rxjs/operators';
downloadImages([url1, url2, url3])
.pipe(
filter(image => image.width > 100), // пропускаємо лише великі картинки
map(image => {
image.classList.add('highlight');
return image;
})
)
.subscribe({
next: image => document.body.append(image),
error: err => console.error(err),
complete: () => console.log('Готово')
});
```
Таким чином, як і у випадку з Promise, можна будувати ланцюжки обробки. Але Observable значно гнучкіші: вони дозволяють працювати не лише з одним значенням, а з динамічною послідовністю даних у часі.
Для глибшого занурення рекомендую офіційний гайд Observable на RxJS.dev. та відео уроки Observables. Частина 1, та Observables. Частина 2[1]
Практичні поради по работі за асинхроним кодом
Не змішуйте підходи без потреби
Якщо почали писати з async/await, не вставляйте всередину .then() без особливої причини. Це ускладнює читання.
Обробляйте помилки
Використовуйте try/catch для async/await або .catch() для Promise. У випадку Observable завжди додавайте обробку error у subscribe().
Скасовуйте непотрібні операції
Для Observable використовуйте unsubscribe(), коли потік більше не потрібен. Для fetch можна застосувати AbortController, щоб зменшити навантаження й уникнути витоків пам’яті.
Уникайте "Pyramid of Doom"
Замість вкладених callback застосовуйте Promise, async/await або Observable.
Використовуйте паралельне виконання
Якщо операції незалежні, запускайте їх одночасно через Promise.all().
Ізолюйте логіку обробки
Розділяйте завантаження даних та маніпуляції з DOM. Це спростить тестування й повторне використання коду.
Логуйте стан і помилки
Під час розробки виводьте у консоль ключові події асинхронних операцій, щоб відстежувати їх послідовність.
Пам’ятайте про event loop
Розуміння різниці між мікрозадачами й макрозадачами допоможе прогнозувати порядок виконання коду.
Перевіряйте сумісність середовища
Деякі API можуть бути відсутні у певних середовищах (наприклад, fetch у Node.js доступний лише починаючи з версії 18).
300+ запитань щодо JavaScript на співбесіді
Автор: Влад Сверчков
Дорогие друзья! Предлагаем вашему вниманию перевод статьи, опубликованной на DOU.ua 21 декабря 2020 года. Оригинальная версия на украинском языке доступна по ссылке.
На этот раз предлагаем ознакомиться с актуальными вопросами, которые задают на технических интервью по JavaScript. Естественно, мы говорим о широком спектре специализаций, поэтому выбирайте свое направление и готовьтесь.
Junior
Общие:
1. Какие методы HTTP-запросов вы знаете?
2. Какие версии HTTP-протокола вам известны?
3. Какие знаете коды ответа (состояния) HTTP?
4. Что такое Cross-Origin Resource Sharing? Как устранить проблемы с CORS?
5. Что такое cookie?
6. Какой максимальный размер cookie?
7. Что означает директива use strict?
8. Чем JS отличается при работе на front-end и back-end?
9. Что такое статическая и динамическая типизации?
10. Как клиент взаимодействует с сервером?
11. Что такое REST?
12. Объяснить понятие мутабельность/иммутабельность? Какие типы являются мутабельными и наоборот?
13. Как искать ошибки в коде? Используете ли вы дебаггер?
14. Каких известных людей из мира JS знаете?
JS Core
15. Какие существуют типы данных в JS?
16. Как проверить, является ли объект массивом?
17. Как проверить, является ли число конечным?
18. Как проверить, что переменная равна NaN?
19. Чем отличается поведение isNaN() и Number.isNaN()?
20. Сравните ключевые слова var, let, const.
21. Что такое область видимости?
22. Что такое деструктуризация?
23. Для чего предназначены методы setTimeout и setInterval?
24. Сравните подходы работы с асинхронным кодом: сallbacks vs promises vs async / await.
25. Можно ли записывать новые свойства / функции в прототипы стандартных классов (Array, Object и т. д.)? Почему нет? В каких случаях это делать можно? Как обезопасить себя, если нужно расширить прототип?
26. Назовите методы массивов, какие помните, и скажите, для чего они нужны.
27. Какие методы перебора массива знаете? В чем их отличие?
28. Как работают операторы присваивания / сравнения / строчные / арифметические / битовые и т. д.?
29. Опишите назначение и принципы работы с коллекциями Map и Set.
30. Что означает глубокая (deep) и поверхностная (shallow) копия объекта? Как сделать каждую из них?
Ответы на некоторые из этих вопросов вы можете найти в видео курсе JavaScript Стартовый (урок 3, урок 5, урок 10), JavaScript Базовый (урок 3, урок 13, урок 19), ECMAScript 6 (урок 6).
Функции:
31. Какая разница между декларацией функции (function declaration) и функциональным выражением (function expression)?
32. Что такое анонимная функция?
33. Расскажите о стрелочных функциях (arrow function). В чем заключаются отличия стрелочных функций от обычных?
34. Что такое и для чего используют IIFE (Immediately Invoked Function Expression)?
35. Что такое hoisting, как он работает для переменных и функций?
36. Что такое замыкание (closure) и какие сценарии его использования?
37. Как вы понимаете замыкания? Что будет выведено в консоли в этом случае?
var f = function() {
console.log(1);
}
var execute = function(f) {
setTimeout(f, 1000);
}
execute(f); // что выведет в консоль и почему
f = function() {
console.log(2);
}
38. Что такое рекурсия?
39. Что означает ключевое слово this?
40. Что такое потеря контекста, когда происходит и как ее предотвратить?
41. Методы функций bind / call / apply - зачем и в чем разница?
Ответы на некоторые из этих вопросов вы можете найти в видео курсе JavaScript Стартовый (урок 11, урок 12) и JavaScript Базовый (урок 13, урок 14).
Front-end
42. Что такое DOM?
43. Сравните атрибуты подключения скрипта async и defer в HTML-документе.
44. Какая разница между свойствами HTML-элементов innerHTML и innerText?
45. Опишите процесс всплытия (bubbling) событий в DOM.
46. Как остановить всплытие (bubbling) события?
47. Как остановить дефолтную обработку события?
48. Чему равен this в обработчике событий (event handler)?
49. Что такое LocalStorage и SessionStorage? Какой максимальный размер LocalStorage?
50. Как получить высоту блока? Его положение относительно границ документа?
51. Что такое webpack?
52. Чем отличается dev-сборник от prod?
Ответы на некоторые из этих вопросов вы можете найти в видео курсе JavaScript Базовый (урок 1, урок 6, урок 7, урок 8, урок 17) и ECMAScript 6 (урок 1).
Верстка
53. Что такое блочная модель CSS?
54. Какие способы центрирования блочного контента по горизонтали и вертикали знаете?
55. Какие подходы в верстке вам известны (float, flex, grid, etc.)?
56. Как сделать приложение responsive?
57. Какие есть принципы семантической верстки?
58. Зачем нужны префиксы для некоторых CSS-свойств (-webkit-, -moz- и т. д.)?
59. Как упростить написание кросс-браузерных стилей?
60. Практические задачи: прокомментировать и исправить пример плохого CSS или HTML.
61. Что такое CSS-препроцессоры? С какими работали? Что нового они приносят в стандартный CSS?
Ответы на некоторые из этих вопросов вы можете найти в видео курсе HTML5 & CSS3 Стартовый (урок 5, урок 6), HTML5 & CSS3 Углубленный (урок 4). Курсы Верстка сайта на CSS Grid и Верстка сайта на FlexBox CSS дадут комплексные знания и практические навыки применения технологий FlexBox и Grid.
Angular
62. Перечислите основные компоненты фреймворка (модуль, роут, директива и т .п.).
63. В чем разница между компонентом и директивой?
64. Расскажите о жизненном цикле компонента.
65. Перечислите часто используемые хуки жизненного цикла компонента и расскажите, для чего они нужны?
66. В чем разница между конструктором и ngOnInit-хуком?
67. Как защитить роут от несанкционированного доступа? Какие механизмы предоставляет для этого фреймворк?
68. Что такое Lazy loading, как и для чего используется?
69. Какое назначение RouterOutlet?
70. Как компоненты могут взаимодействовать друг с другом?
71. Как создать two-way binding свойство для компонента?
72. Какие типы форм у фреймворка? В каких случаях и что лучше использовать?
73. Какие состояния у формы и как это можно применить?
74. Зачем нужны сервисы? Как с ними работать?
75. Что такое singleton-сервисы? Каково их назначение? Способ создания?
76. Какие есть способы объявления сервисов?
77. Для чего нужны модули? Сколько их должно быть в проекте?
78. Зачем нужны общие модули (shared)?
79. Какие преимущества типизации в TypeScript?
80. Какие возможности TypeScript можно использовать для типизации (здесь имеются в виду интерфейсы, типы, enum и т. д.)?
81. Какая разница между интерфейсом и классом?
82. В чем разница между интерфейсом и абстрактным классом?
83. Какая разница между интерфейсом и типом?
84. Что такое RxJS? Как он используется во фреймворке? Какие компоненты фреймворка тесно связаны с ним?
85. Чем отличаются Observable и Promise?
86. Для чего нужны Subjects? Какие типы Subjects существуют?
87. Как сделать несколько последовательных запросов к API с помощью HTTP-сервиса и RxJS?
88. Какая разница между switchMap, concatMap, mergeMap?
89. Как можно конфигурировать Angular-приложение?
90. Зачем нужны environment-файлы? Когда их лучше не использовать?
91. В чем разница между «умным» (smart) и «глупым» (dumb) компонентами? В каких случаях применяется каждый из них?
92. В чем разница между NgForm, FormGroup и FormControl и как их применяют для построения форм?
93. Зачем нужен и как работает async pipe?
94. Как следить за развитием фреймворка? Каких известных людей, связанных с Angular, знаете / читаете?
Ответы на некоторые из этих вопросов вы можете найти в видео курсах Angular Базовый и Angular Углублённый.
React
95. Работали ли вы с классовыми компонентами? В чем их особенность?
96. Какие данные лучше хранить в состоянии компонента, а какие передавать через пропсы? Приведите пример.
97. Ознакомлены ли вы с хуками? В чем их преимущества? Приходилось ли делать свои и с какой целью?
98. Знакомы ли вы с фрагментами и порталами? Зачем они нужны?
99. Когда и для чего используют рефы?
100. Какие вы знаете методы жизненного цикла компонента?
101. В каком методе жизненного цикла компонента лучше делать запросы на сервер? Почему?
102. В каком методе жизненного цикла компонента лучше делать подписку и отписку от листенера? Почему? Зачем отписываться?
103. Был ли опыт работы с контекстом? Когда его стоит использовать?
104. В чем особенность PureComponent?
105. Работали ли вы с мемоизоваными селекторами (memoized selectors)? Для чего их используют и какой принцип работы?
106. В чем видите преимущества библиотеки React?
107. Почему библиотека React быстрая? Что такое Virtual DOM и Shadow DOM?
108. Зачем в списках ключи? Можно ли делать ключами индексы элементов массива? Когда это оправдано?
109. В чем основная идея Redux?
110. Работа со стилями в React.
111. React - это библиотека или фреймворк? Какая разница между этими двумя понятиями.
112. Можно ли использовать jQuery вместе с React? Почему да / нет?
113. Что такое codemod?
114. Приходилось ли вам настраивать проект React с нуля? С помощью каких инструментов вы это делали?
115. Перечислите все библиотеки, которые использовали в связке с React.
116. Что самое сложное вам приходилось реализовывать с помощью React?
Ответы на некоторые из этих вопросов вы можете найти в видео курсах React Базовый и React Углублённый.
Back-end
117. Что такое REPL?
118. Что такое streams в Node.js?
119. Что такое middleware?
120. Для чего используют функцию setImmediate?
121. Зачем нужен app.param() в express?
122. Что такое token based authentication?
Базы данных
123. Напишите простой запрос для вычисления трех авторов, у которых больше всего книг.
124. Напишите запрос, который выбирает последние три комментарии для конкретного пользователя для двух таблиц: комментарии и пользователи.
125. Спроектируйте простую схему базы данных для библиотеки.
126. Для чего используют SQL-оператор HAVING?
127. Зачем используют SQL-оператор LEFT JOIN?
128. Чем отличается embed- от reference-связи в MongoDB?
129. В одном проекте программисты сохраняют данные в MongoDB-коллекции комментариев, используя такие типы данных (смотрите ниже). Что плохого в этом решении?
id: ObjectID
text: string
author_id: string
created_at: Date
130. В проекте понадобилось внести изменения в структуру таблиц, добавить несколько полей и индексы. Как программисты будут делать это на продакшене?
Ответы на некоторые из этих вопросов вы можете найти в видео курсе SQL Базовый.
Инструменты
131. Каждый раз, когда вы делаете pull, почему-то случается конфликт в последней строке во всех файлах, которые вы редактировали. Что происходит?
132. Что делает команда git fetch?
133. Какой git hygiene подходы вы знаете?
134. Что такое CI / CD? Для чего это нужно?
Практические задания
135. Расскажите, какие есть способы копирования простого объекта типа obj = {a 1, b 2, c 3}
136. Напишите deep clone для объекта.
137. Назовите различные способы, как поменять местами значения двух переменных.
138. Менеджер попросил в задаче поменять статусы из «active, inactive» на «active, removed», но в коде фигурируют только цифры и непонятно, какой статус соответствует какой цифре. Как помочь будущим программистам не лезть в документацию по коду? Вопрос ставят на конкретном примере с кодом.
139. Необходимо сделать мини проект - список пользователей с формой создания / редактирования пользователя:
Для хранения пользователей используйте Firebase (это бесплатно).
Для стилизации используйте Bootstrap.
Минимальный набор полей пользователя:
имя;
фамилия;
электронная почта;
телефон (в формате +380 (XX) XXX-XX-XX)
дата рождения;
будет плюсом - добавление аватара и возможность crop-картинки.
Пользователи должны иметь возможность фильтрации и пагинацию.
Проект должен содержать README-файл с шагами для запуска.
Middle
Общие
1. Расскажите о пирамиде тестирования.
2. Какие типы автоматизированных тестов выпадала возможность писать? Какие библиотеки при этом использовали? Каким инструментам отдаете предпочтение и почему?
3. Что такое unit-тесты? Какое место в пирамиде тестирования занимают unit-тесты?
4. Что такое code coverage? Обязательно 100% покрытие тестами кода?
5. Как запретить браузеру отдавать кэш на HTTP-запрос?
6. Что такое XSS (Cross-Site Scripting)?
7. Расскажите о паттернах Observer, Pub / Sub. Какая между ними разница? Приведите примеры реализации этих паттернов в известных фреймворках / библиотеках / браузерных API.
8. С какой целью может быть использован event listener события fetch self.addEventListener ( 'fetch', event => {})?
9. Что такое Event loop и как он работает? Расскажите о микрозадачах и макрозадачах.
JS Core
10. Какие типы данных бывают в JavaScript? Какой будет результат выполнения кода?
let firstObj = { name: 'Hello' };
let secondObj = firstObj;
firstObj = { name: 'Bye' };
console.log(secondObj.name);
11. Что такое temporal dead zone?
12. Как работает boxing / unboxing в JavaScript?
13. В чем разница между оператором in и методом hasOwnProperty?
14. Опишите, с помощью чего в JS реализуются такие ООП-парадигмы, как инкапсуляция, полиморфизм, абстракция?
15. Что такое прототип? Как работает прототипное наследование в JS? Объясните работу кода.
function Main () {}
Main.prototype = { protected: true };
const obj = new Main();
Main.prototype = { protected: false };
console.log('Object protection: ', obj.protected);
16. Какая разница между композицией и наследованием?
17. Почему не стоит использовать конструкторы типа new String?
18. Расскажите о базовом устройстве и механизме работы Event loop.
19. Что такое записи (records) и кортежи (tuples)? Чем они отличаются от обычных объектов?
20. Какие различия в поведении ES5 функции-конструктора и ES2015 класса?
21. Как реализовать паттерн «Модуль»?
22. Почему typeof null возвращает object?
23. Что такое приведение (преобразование) типов в JS?
24. Что такое явное и неявное приведение (преобразование) типов данных в JS? Как происходит преобразование типов в следующих примерах:
{}+[]+{}+[1]
!!"false" == !!"true"
['x'] == 'x'
25. Что такое Garbage Collector?
26. Опишите основные принципы работы «сборщика мусора» в JS-движках (engines).
27. Опишите назначение и принципы работы с коллекциями WeakMap и WeakSet? Чем они отличаются от коллекций Map и Set соответственно?
28. Чем отличается Observable от Promise?
29. Что такое Promise? Назовите порядок выполнения then и catch в цепочке.
Promise.resolve(10)
.then(e => console.log(e)) // ??
.then(e => Promise.resolve(e))
.then(console.log) // ??
.then(e => {
if (!e) {
throw 'Error caught';
}
})
.catch(e => {
console.log(e); // ??
return new Error('New error');
})
.then(e => {
console.log(e.message); // ??
})
.catch(e => {
console.log(e.message); // ??
});
30. Расскажите о последовательном и параллельном выполнении асинхронных функций. В чем разница между Promise.all() и Promise.allSettled()?
31. Что такое дескрипторы свойств объектов? Расскажите об их практическом применение.
32. Назовите несколько способов создания постоянного (неизменного) объекта в JavaScript.
33. Как создать свойство у объекта, которое нельзя будет изменить?
34. Зачем нужен конструктор Proxy? Приведите пример использования.
35. Что такое ArrayBuffer? В чем разница между Uint32Array и Float32Array? Каков результат выполнения кода?
const uint32Array = new Uint32Array();
Array.isArray(uint32Array);
36. Каким будет результат сравнения?
const url = “HTTPs://xyz.com/path<to>page.html”;
encodeURI(url) == encodeURIComponent(url);
37. Расскажите о генераторах и итераторах.
38. Объясните, что делает приведенный ниже код:
function * fn(num) {
for (let i = 0; i < num; i += 1) {
yield console.log(i);
}
}
const loop = fn(5);
loop.next();
loop.next();
39. Расскажите о типе данных Symbol и его практическом применении. Как перевести число с 10-разрядной системы в 16 (2,8) разрядную систему счисления?
Ответы на некоторые из этих вопросов вы можете найти в видео курсе JavaScript Стартовый (урок 3, урок 4, урок 13, урок 14) и JavaScript Базовый (урок 18, урок 19), ECMAScript 6 (урок 6).
Функции
40. Объясните, что означает currying. Приведите пример использования на практике.
41. Приведите пример функции с мемоизацией. Когда следует применять эту технику?
42. Что такое чейнинг функций? Напишите пример с использованием этого подхода.
43. В чем разница между function и arrow function? Каким будет результат выполнения кода?
const pluckDeep = key => obj => key.split('.').reduce((accum, key) => accum[key], obj)
const compose = (...fns) => res => fns.reduce((accum, next) => next(accum), res)
const unfold = (f, seed) => {
const go = (f, seed, acc) => {
const res = f(seed)
return res ? go(f, res[1], acc.concat([res[0]])) : acc
}
return go(f, seed, [])
}
Front-end
44. В чем принципиальная разница между событиями mouseleave и mouseout?
45. В каком порядке обрабатываются пользовательские события в DOM (click, mouseover и т .д.)? FIFO или LIFO?
46. Что такое Event bubbling и Event capturing?
47. Сравните методы объекта event stopPropagation и stopImmediateProparation.
48. Какие есть подходы оптимизации производительности веб-страницы?
49. Как реализован механизм same-origin policy в браузере? На какие браузерные API он распространяется?
50. Назовите способы хранения данных в браузере. Сравните их.
51. Web worker`ы. Опишите особенности передачи данных между worker`амы и основным потоком, между разделенными worker`амы.
51. Что такое Transferable-объекты?
52. Расскажите о способах оптимизации выполнения ресурсоемких операций JS для улучшения производительности рендеринга контента на странице.
53. Почему ResizeObserver вызывает события изменения размера до воспроизведения элемента, а не после?
54. Расскажите, как вы понимаете Web Accessibility?
55. Опишите алгоритм создания функционала, который обеспечивает чтение содержимого .txt файла при перетаскивании его из файловой системы в окно браузера.
56. Что такое Virtual DOM?
Ответы на некоторые из этих вопросов вы можете найти в видео курсе HTML5 & CSS3 Углубленный (урок 3), JavaScript Базовый (урок 1, урок 2, урок 3).
Верстка
57. Объясните разницу между единицами измерения px, em, rem.
58. Для чего нужны CSS-переменные? Приведите несколько примеров использования.
59. Что произойдет при добавлении следующего селектора?
* {Box-sizing: border-box; }
60. Как адаптировать страницу для печати?
61. Опишите особенности кастомизации стилей стандартных элементов форм.
62. Что такое progressive рендеринг? Какие подходы используются?
63. Назовите несколько способов реализации lazy-loading медиаресурсов на странице.
64. Назовите популярные шаблонизаторы для фронтенд-разработки. Опишите особенности их использования.
65. Назовите популярные CSS-методологии и их различия.
66. Как работает CSS Grid?
67. Какие форматы изображений поддерживают анимацию?
68. Как отследить прогресс / окончание CSS @keyframes анимаций или плавных переходов, реализованных с помощью transition, в JS?
69. Какие CSS-свойства могут быть обработаны непосредственно через GPU? Что такое композитные слои и почему большое их количество может привести к аварийному завершению работы браузера на мобильных устройствах?
70. Как переиспользовать Инлайн SVG-элементы на странице?
71. Опишите способы оптимизации SVG-файлов.
72. Как реализовать иконочный шрифт из определенного набора SVG-файлов?
73. Что такое ложное жирное или ложное курсивное (Faux) начертание шрифтов?
74. Что такое #shadow-root в инспекторе HTML-страницы?
75. Зачем нужны Custom Elements?
76. Почему удаление лишних символов пробелов / символов переноса в HTML не отражается на конечной производительности загрузки страницы?
77. Что такое контекст отображения canvas? Какие существуют типы контекста для рендеринга двумерной и трехмерной графики?
Ответы на некоторые из этих вопросов вы можете найти в видео курсе HTML5 & CSS3 Углубленный.
Angular
78. Как работает Dependency injection? Зачем это нужно? Расскажите об использовании кастомных инжекторов.
79. Что такое zone.js? Для чего Angular использует зоны? С какой целью можно использовать NgZone-сервис?
80. Как работает Change detection? Как можно оптимизировать компонент с помощью схем Change detection? Какие еще есть приемы для оптимизации рендеринга (связанные с Change detection)?
81. Как выполнить конфигурацию HTTP-сервиса? Зачем она нужна? Обработка HTTP-ошибок?
82. Какие есть подходы к организации работы с данными?
83. Как подготовить сборник к деплою?
84. Что такое NgRx? Когда стоит использовать?
85. В каких случаях лучше использовать Renderer-сервис вместо нативных методов? И наоборот?
86. Как работают и для чего нужны резолверы? Как получить данные, загруженные резолверами?
87. Как работают и зачем нужны динамические компоненты? Приведите примеры их целесообразного использования.
88. Какая разница между @ViewChild и @ContentChild?
89. Что делает код и как иначе можно связать класс компонента с переменной?
@HostBinding ( 'class.valid') isValid;
90. Как можно кэшировать данные, используя сервисы или RxJS?
91. Что такое асинхронная валидация форм? Когда применяется и как реализуется?
92. Зачем нужна forRoot-функция модуля?
93. Какая разница между декларированием и экспортом компонента из модуля?
94. Почему плохо «провайдить» сервис с shared-модуля в lazy-loaded модуль? (Вопрос о scope модулей.)
95. Что такое :: ng-deep и для чего используется?
96. Какие тесты можно запустить для Angular-программы? Какие инструменты используют для тестирования Angular-программы?
97. Как протестировать API-сервис?
Ответы на некоторые из этих вопросов вы можете найти в видео курсах Angular Базовый и Angular Углублённый.
React
98. Что такое JSX? Что лежит в его основе?
99. Как работает алгоритм Virtual DOM?
100. Для чего нужно свойство key во время рендеринга списков?
101. В чем разница между функциональными и классовыми компонентами?
102. Зачем и когда нужно передавать props в super() при использовании классовых компонентов?
103. Почему нужно использовать setState() для обновления внутреннего состояния компонента?
104. В чем заключается принцип «подъема состояния»?
105. Какие библиотеки менеджмента состояния React-приложения вы знаете? Зачем они нужны?
106. Когда следует использовать Redux? Какие есть альтернативы?
107. Redux vs Mobx?
108. Расскажите о базовом принципе работы React Hooks.
109. В чем разница между createRef и useRef?
110. Когда следует использовать React refs? Когда не стоит?
111. Какие недостатки библиотеки React видите?
112. Какие паттерны используете вместе с React?
113. Как относитесь к типизации вместе с React?
114. Как построить хорошую архитектуру React-проекта?
115. Оптимизация React-приложений? Как измерить производительность программы?
116. Можно ли приложение на React встроить в другое приложение на React?
Ответы на некоторые из этих вопросов вы можете найти в видео курсах React Базовый и React Углублённый.
Back-end
117. Почему Node.js однопоточный, а не многопоточный?
118. Что такое event driven development?
119. Сравните fork() и spawn() методы.
120. Расскажите о Node.js фреймворках, которые использовали. Какая между ними разница?
121. Опишите словам код ендпоинта, который должен сохранить с клиента файл размером 4 гигабайта и положить его на S3 или другой CDN.
122. Что такое микросервисы, зачем их используют?
123. В каких случаях вы бы выбрали монолит, а в каких - микросервисы?
124. Как понять, что приложение в определенный момент работает исправно?
125. Как понять, что приложение за последние три дня работал исправно?
126. Как происходит проверка правильности пароля при использовании bcrypt?
127. Что такое JWT?
128. Джуниор прислал код на ревью. Что здесь не так? Как исправить?
router.post ( '/ users', async (req, res, next) => {
const user = await db.createUser (req);
if (user) {
return res.json (users);
}
res.json ({error: "can not create user"})
})
Базы данных
129. Что такое Redis и для чего его используют?
130. Какие базы данных использовали? Какая разница между SQL и NoSQL?
131. Для двух таблиц - комментарии и пользователи - напишите запрос, который выбирает последние три комментария для каждого пользователя.
132. Я как заказчик прошу выбрать вас базу данных для нового проекта. Ваши действия?
Инструменты и другое
133. Для чего нужен package-lock.json?
134. В чем разница между npm install и npm ci?
135. Для чего нужны бандлеры?
136. Расскажите о модульном подключении скриптов. Приведите пример использования загрузчиков / бандлеров модулей.
137. Чем различаются git merge и git rebase?
138. Что такое staging area в git?
139. Опишите процесс code review. Назовите основные правила, способы разрешения конфликтов и споров во время его проведения.
Практические задания
140. Напишите функцию Sleep (ms), которая останавливает выполнение async-функции на заданный промежуток времени.
141. Реализуйте один из методов массива (например, splice).
142. Напишите функцию с RegExp для нахождения всех HTML-ссылок в строке.
143. Реализуйте функцию, которая исполнит callback для всех элементов определенной ветви DOM-дерева.
144. Реализуйте таблицу с виртуальным скролом.
145. Реализуйте функцию преобразования URL query строки в JSON.
const inData = "user.name.firstname=Bob&user.name.lastname=Smith&user.favoritecolor=Light%20Blue";
function queryObjectify(arg) {
// ??
}
queryObjectify(inData)
/* Результатом виконання для вхідного рядка, повинен бути наступний об’єкт
{
'user': {
'name': {
'firstname': 'Bob',
'lastname': 'Smith'
},
'favoritecolor': 'Light Blue'
}
};
*/
146. Реализуйте функцию нахождения пересечения двух массивов.
const first = [1, 2, 3, 4];
const second = [3, 4, 5, 6];
function intersection (a, b) {
// ??
}
intersection(first, second) // -> [3, 4]
147. Реализуйте функцию / класс для генерации HTML.
const HTMLConstruct = {};
HTMLConstruct.span('foo'); // -> <span>foo</span>
HTMLConstruct.div.span('bar'); // -> <div><span>bar</span></div>
HTMLConstruct.div.p(
HTMLConstruct.span('bar'),
HTMLConstruct.div.span('baz')
); // -> <div><p><span>bar</span><span>baz</span></p></div>
148. Если есть проект с ограниченными сроками и некритичной производительностью, чем будете руководствоваться при выборе библиотек, подходов? Или все же будете обращать внимание на производительность? Или наоборот: сроки нелимитированные, производительность важна. Ваши действия?
Senior
Общие
1. Расскажите о функциональном программировании.
2. Что такое TDD (Test Driven Development) / BDD (Behaver Driven Development)?
3. Расскажите подробно о работе HTTPS.
4. Какой стек технологий можно выбрать для реализации клона какого-нибудь известного проекту и почему?
5. Имеется проект на старых технологиях, необходимо в него вносить изменения. Как это сделать лучше всего?
6. Если у кандидата есть опыт работы с несколькими фреймворками: какой будете использовать для следующего проекта? Какие факторы будут влиять на выбор?
7. Что такое V8 Engine?
JS Core
8. Реализация паттерна Class Free OOP (HTTPs://observablehq.com/@bratter/class-free-oop).
9. Патерн async disposer (HTTPs://advancedweb.hu/what-is-the-async-disposer-pattern-in-javascript).
10. использование регулярных выражений. Когда приемлемо / неприемлемо? Как они работают? Как можно сделать читабельный код?
Front-end
11. Как браузер определяет, можем ли мы общаться между вкладками?
12. Что такое Content Security Policy?
13. Как избежать загрузки кэшированных файлов скриптов и стилей?
14. Что такое requestAnimationFrame?
15. Расскажите о микросервисной архитектуре Front-end App.
16. Что такое Shadow DOM?
17. Сравните nextElementSibling и nextSibling.
18. Какие знаете метрики веб-сайта?
Angular
19. Как проводится конфигурация NgZone-модуля? Когда это необходимо?
20. Что раздражает в фреймворке? Что бы вы изменили?
21. Если бы вы решали, что добавить в следующем релизе фреймворка, какая фича это была бы?
22. Писали ли вы кастомные декораторы? Если да, то зачем?
23. Сделать ревью кода и дать замечания по архитектуре.
24. Расскажите, как бы вы делали такие фичи. Опишите архитектуру фичи в приложении.
Back-end
25. Сравните Common.js с AMD Modules и ES6 Imports.
26. Какой фреймворк выбрали бы для бэкенда, почему?
27. Опишите своими словами, как работает OAuth v2.
28. Есть проект с источниками памяти, как их обнаружить, устранить и предотвратить это в будущем?
29. Есть проект с performance issues, как их обнаружить, устранить и предотвратить в будущем?
Базы данных
30. Какие альтернативные виды баз данных используете?
31. Что такое RDS и почему он иногда не подходит?
32. Что такое SQL Injections и как их избежать?
33. Почему для запросов в БД надо использовать плейсхолдеры?
34. Как спроектировать кластер на MongoDB?
35. Для чего используют MongoDB Aggregation framework?
36. Расскажите о GraphQL.
Инструменты
37. Можете ли вы описать суть методологии git flow в двух словах?
38. Что означает требование делать squash commits во время rebase?
39. Каково ваше мнение об альтернативных системы контроля версий (Version Control System)?
40. Какие конвенции знаете и используете для git?
41. Расскажите о своем опыте использования / внедрения CI / CD.
42. Необходимо настроить деплой проекту на несколько сред. Расскажите, как бы вы построили процесс? Какие инструменты использовали бы?
Практические задания
43. Реализуйте асинхронный метод filter для Array (должны работать await).
44. Реализуйте функцию reduce при помощи рекурсии.
45. Как можно было бы сделать toggle-компонент, как в iPhone, без использования JS?
Благодарим за помощь в подготовке статьи Вячеславу Колдовскому, Ивану Рыженку, Николаю Галкину, Александру Бурмистрову, Владу Балабашу, Андрею Шумаде, Ивану Кувацкому, Андрею Кладочному.
Введення в розробку програм під iOS. Частина 6
Автор: Volodymyr Bozhek
Здравствуйте, дорогие читатели.
В этом уроке мы:
Установим менеджер установки пакетов “Brew”;
Научимся пользоваться базой данных “Mongo DB” и изучим библиотеку “Mongoose”;
Установим и сконфигурируем базу данных “Mongo DB”;
Научимся запускать демон (службу) “Mongod” и подключаться к ней;
Научимся просматривать документы базы данных “Mongo DB” с помощью приложения “Robomongo”;
Создадим REST сервисы для товаров и пользователей с использованием “NodeJS”;
Научимся тестировать REST сервисы с помощью расширения “Chrome” браузера “Postman”;
Итак, вы скорее всего задались вопросом, почему же я выбрал именно такие технологии для написания REST сервисов. Почему не выбрал то, что уже давно у всех на слуху, такие технологии как Web API + Entity Framework. Ответ прост, я выбрал ровно те технологии, которые явно подходят платформе, на которой мы ведем разработку macOS.
Да, можно было установить Xamarin Community Edition, в нем создать ASP.NET проект и сделать сервисы на Mono.NET.
Еще был вариант сделать сервисы на виндовс платформе, развернутой на виртуальной машине в веб сервере IIS с сетевым адаптером мост. Это для того, чтобы веб сайт и сервисы были доступны на хостовой машине macOS в браузере.
Возможно, в одном из моих будущих видео курсов по разработке iOS приложений я буду использовать именно платформу Windows и Visual Studio для разработки REST сервисов.
Но в этом уроке мы будем делать сервисы на NodeJS, и вы сами убедитесь в том, насколько это просто и как мало кода надо для этого написать :)
В качестве среды разработки я буду использовать WebStorm, он довольно хорошо себя оправдал как один из продуктов JetBrains.
В этом уроке мы не будем работать с приложением “Warehouse” под iOS, поскольку мы должны приступить к изучению библиотеки “Alamofire”. А для нее необходимы REST сервисы, которых у нас сейчас нет. Показывать работу на всяких httpbin, parse и других сервисах тестирования я не буду, этого полно в сети интернет, вы и сами будете видеть это в поиске нужной вам информации.
“Alamofire” - это асинхронная сетевая библиотека для работы с REST сервисами. В большинстве туториалов не рассказывается, как сделать REST сервисы и клиент к ним на разных платформах.
Мне хотелось бы нарушить этот стереотип и предоставить вам учебные примеры по созданию полнофункционального REST сервиса и полнофункционального iOS клиента в составе приложения “Warehouse” к нему. Проще говоря, дать готовое решение для быстрого понимания, что и как делается.
Это то, чего обычно не хватает новичкам и то, чего обычно нигде не выкладывают. Приходится самостоятельно разбираться и искать нужную информацию.
Откройте “WebStorm”. Выберите в меню “File -> New Project”. Выделите тип проекта “Node.js Express App”.
В поле “Location” укажите название проекта “Warehouse” и путь, по которому вы будете сохранять данный проект.
В поле “Template” выберите “EJS”. Нажмите кнопку “Create”.
Вы увидите диалоговое окно с предложением, откуда взять библиотеку “NodeJS”.
Оставьте пункт по умолчанию “Download from the Internet” и нажмите кнопку “Configure”.
Будет загружен из сети интернет “NodeJS”, “Express” и другие библиотеки.
Панель навигации будет выглядеть у вас так:
Рассмотрим, что создал нам данный шаблон.
В папке “bin” хранится файл “www”, в нем находится настройка сервера “NodeJS”, с этого файла происходит запуск нашего сервера.
В папке “node_modules” находятся библиотеки, которые были автоматически загружены шаблоном проекта NodeJS.
В папке “public” находятся ресурсы, используемые нашим сервером (картинки, CSS стили, скрипты).
В папке “routes” находятся скрипты, которые должны содержать маршрутизацию относительно текущего URL, введенного пользователем.
Например, файл с именем “users.js” вызывется, когда пользователь введет в браузере URL: “http://localhost:{port}/users”.
Файл “index.js” вызывется, когда пользователь введет URL: “http://localhost:{port}”.
Если сравнивать с паттерном MVC (Model View Controller), то в папке “routes” находятся “контроллеры”.
В папке “views” находятся представления. Расширение “*.ejs” говорит о том, что содержимое данного файла будет транслироваться через библиотеку “Express JS”.
Данная библиотека создана в помощь, чтобы можно было проще создавать маршрутизацию в NodeJS и проще создавать пользовательский интерфейс.
Внутри этих файлов “*.ejs” содержится обычная “HTML” разметка. Файл маршрутизации и файл представления должны называться одинаково, если они будут связаны.
В текущем проекте связаны только “index.js” и “index.ejs”. Маршрут “users.js” не имеет явного представления, для него преставление генерируется средствами “NodeJS”.
Наша задача создать только REST сервисы, поэтому работу с “EJS” мы не будем рассматривать в данном уроке.
Рассмотрим содержимое файла “www” в папке “bin”.
На 7 строке через библиотеку “Require JS” мы подключаем содержимое модуля “app.js” в текущий исполняемый модуль “www” и запускаем это содержимое на исполнение.
В файле “app.js” содержатся настройки для работы нашего сервера.
На 8 строке мы задаем режим отладки для нашего сервера.
На 9 строке мы подключаем модуль “http” для работы с HTTP запросами.
На 15 строке задается порт “3000”, на этом порту сервер будет принимать входящие запросы к нему.
На 16 строке устанавливает этот порт для свойства “port” сервера.
На 22 строке создается сервер на основе настроек экземпляра “app”.
На 28 строке сервер запускается и начинает прослушивание на порту “3000”.
На 29 строке привязывается функция “onError”, вызываемый при возникновении ошибок.
На 30 строке привязывается функция “onListening”, вызываемая при начале прослушивания запросов сервером.
Остальной код в данном модуле не представляет для нас интереса.
Чтобы запустить приложение, выполните в меню “Run -> Run bin/www”, сервер запустится.
Затем откройте браузер и введите URL: “http://localhost:3000”, вы увидите приветствие.
Чтобы остановить сервер, выполните в меню “Run -> Stop”.
Теперь необходимо установить базу данных “Mongo DB”. Подробнее об установке вы можете прочитать тут. Проще всего устанавливать базу данных через менеджер пакетов “Brew”.
Давайте установим его. Перейдите в браузере по адресу, на сайте будет предложено скопировать строку “/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)” в терминал.
Откройте терминал и скопируйте в него строку установки “Brew”. После установки вы увидите следующее:
Теперь необходимо установить базу данных “Mongo DB”. Установка базы данных через “Brew” проще тем, что “Brew” сам заполняет нужные переменные среды окружения и вам не надо этого делать вручную в случае с установкой базы данных вручную.
Перейдите в “WebStorm”, откройте внутри него терминал. И введите команду “brew install mongodb && mongod”, данная команда скачает и установит “Mongo DB”, а также выполнит настройки по умолчанию для демона “mongod”.
Выполните в терминале команду “sudo mkdir -p /data/db”. Введите свой пароль и нажмите кнопку “Enter”. Данная команда создаст папку “data” и в ней папку “db”, эта папка используется по умолчанию для добавления базы данных “Mongo DB”.
Команда “sudo” используется, чтобы выполнить остальную часть команды от имени администратора.
Теперь необходимо установить в наш проект библиотеку “Mongoose” для осуществления возможности работы с базой данных их кода приложения сервера .
Выполните в терминале команду “npm install mongoose”. Документацию по этой библиотеке можно почитать тут:
Данную команду мы выполняли через встроенный в NodeJS менеджер пакетов, так как устанавливаем данную библиотеку исключительно для нашего проекта, а не глобально.
Откройте терминал, введите команду “mongod”.
Данная команда запускает сервер базы данных “Mongo DB”, который принимает входящие подключения на порту “27017”. На картинке выше вы можете в этом убедиться “waiting for connections on port 27017”.
Демон запустили, теперь перейдите в “WebStorm”, в терминале внутри введите команду “mongod –version”, вы увидите версию базы данных “Mongo DB”, которая была установлена на ваш компьютер.
Теперь необходим клиент с GUI для работы с базой данных. Откройте браузер, перейдите по адресу, нажмите кнопку “Download”, скачайте и установите приложение.
После установки приложения откройте его. Нажмите на иконку:
Откроется приложение “Robomongo”.
Нажмите кнопку “Connect to local or remote Mongo DB instance”. Откроется диалоговое окно подключения к базе данных.
Нажмите кнопку “Create”. Откройте диалоговое окно настройки подключения к базе данных.
Заполните настройки, как показано на картинке выше и только на вкладке “Connection”, нажмите кнопку “Save”. После этого в окне “Mongo DB connections” у вас появится добавленное подключение. Выделите его и нажмите кнопку “Connect”.
Нажмите правой кнопкой в панели навигации по “Warehouse” и в контекстном меню выберите пункт “Create Database”.
В поле “Database Name” введите “warehouse”, нажмите кнопку “Create”.
На картинке выше видно, что база данных “warehouse” была успешно добавлена.
Супер :)
Теперь надо добавить в проект модель и схему базы данных, они создаются с помощью библиотеки “Mongoose”.
Перейдите в “WebStorm”. В панели навигации, нажмите правой кнопкой по “Warehouse”, в контекстном меню выберите “New -> Directory”. Создайте папку с именем “models”.
Создайте в папке “models” модули “Product.js” и “User.js”. А в папке “routes” создайте модули “auth.js”, “products.js”.
Откройте модуль “Product.js”, заполните его, как показано на картинке ниже:
На 1 строке мы подключаем библиотеку “mongoose” и создаем ее экземпляр с именем “mongoose”.
На 2 строке мы правым операндом создаем схему таблицы товаров и присваиваем ее левому операнду с именем “ProductSchema”. Таблица товаров содержит поля:
скрытое поле “_id”, типа “String”, в этом поле содержится уникальный идентификатор строки.
скрытое поле “__v”, типа “Number”, в этом поле содержится версия API по умолчанию 0. Версия API нужна для того, чтобы можно было менять реализацию сервисов и иметь несколько версий для обратной совместимости.
поле “productImage”, типа “String”, тут будет храниться название картинок из нашего проекта под iOS, названия от “tool001” до “tool012”.
поле “productName”, типа “String”, тут будет храниться название товара.
поле “productDescription”, типа “String”, тут будет храниться описание товара.
На 7 строке мы правым операндом создаем экземпляр модели с именем “Product” и указываем создать экземпляр на основе схемы, описанной в экземпляре “ProductSchema”. Библиотека “mongoose” создает данный экземпляр и присваивает его левому операнду.
Свойство “exports” содержит экземпляры объектов, которые будут доступны из модуля при подключении его через библиотеку “Require JS”.
Откройте модуль “User.js”, заполните его, как показано на картинке ниже:
На 1 строке мы подключаем библиотеку “mongoose” и создаем ее экземпляр с именем “mongoose”.
На 2 строке мы правым операндом создаем схему таблицы товаров и присваиваем ее левому операнду с именем “UserSchema”. Таблица пользователей содержит поля:
скрытое поле “_id”, типа “String”, в этом поле содержится уникальный идентификатор строки.
скрытое поле “__v”, типа “Number”, в этом поле содержится версия API по умолчанию 0. Версия API нужна для того, чтобы можно было менять реализацию сервисов и иметь несколько версий для обратной совместимости.
поле “userName”, типа “String”, тут будет храниться логин пользователя.
поле “userPwd”, типа “String”, тут будет храниться пароль пользователя.
поле “userDesc”, типа “String”, тут будет храниться описание пользователя.
На 7 строке мы правым операндом создаем экземпляр модели с именем “User” и указываем создать экземпляр на основе схемы, описанной в экземпляре “UserSchema”. Затем присваем созданный экземпляр свойству “exports” данного модуля.
Откройте модуль “auth.js”, заполните его в соответствии с содержимым ниже:
На 1 строке подключаем модуль “express” и создаем его экземпляр с именем “express”.
На 2 строке создаем экземпляр маршрутизатора запросов с именем “router”.
На 3 строке подключаем модуль “User.js” и создаем его экземпляр с именем “User”.
На 4 строке строим маршрут типа “http://localhost:3000/auth/”.
На экземпляре “router” вызываем функцию “post”. Вызов данной функции говорит, что созданный с помощью него маршрут будет доступен только через HTTP глагол POST. Первым аргументом задаем маршрут, вторым аргументом задаем функцию обработчик, который будет вызван при переходе по данному маршруту с учетом заданного HTTP глагола. Т.е. когда пользователь отправит POST запрос по адресу.
Функция обработчик принимает три аргумента.
Первый аргумент “request” содержит экземпляр запроса по данному маршруту. Второй аргумент “response” содержит экземпляр ответа по запросу по данному маршруту. В этот экземпляр можно добавлять любой ответ, который вы хотите, чтобы пользователь получил.
Третий аргумент “next” содержит текущий итератор в стеке запросов по маршрутизации. Данный экземпляр необходим, чтобы была возможность перейти на следующую итерацию в стеке маршрутизации.
Сам по себе сервер NodeJS работает асинхронно и никогда никого и ничего не ждет, это нужно учитывать при работе с ним.
На 5 строке мы выводим сообщение на консоль.
На 6 строке мы на экземпляре “User” вызываем функцию “find”, в которую единственным аргументом передаем специальную функцию обработчик, в которой будет содержаться результат данной операции. Функция “find” получает все записи из таблицы “User” и присваивает их в JSON формате второму аргументу функции обработчика с именем “data”.
Для примера, в “data” может содержаться такой JSON:
“[{_id:'789787sdfsd78sdfsd7', __v:0, userName: “Test1”,...},{_id:'4444447sdfsd78sdfsd7', __v:0, userName: “Test2”,...}]”.
Где квадратные скобки - это массив, а в фигурных скобках - это экземпляр JSON.
В аргументе “err” содержится экземпляр ошибки, если произошла ошибка при выполнении данной функции “find”.
На 7 строке мы создаем экземпляр объекта с именем “res”, данный объект содержит свойство “Error”, которое инициализировано значением по умолчанию “Authorization Error”. Как вы уже поняли, это текст ошибки, который вернется на клиент в случае ошибки авторизации клиента.
На 8 строке мы проверяем, если при получении данных через функцию “find” произошла ошибка и аргумент “err” не содержит значение “undefined”, мы обращаемся к экземпляру “next” и говорим серверу выполнить следующую итерацию маршрутизации и вернуть ошибку на клиент. На клиент средствами NodeJS будет возвращена “Stack Trace” ошибки.
На 9 строке, если ошибки не было, мы выполняем цикл foreach по массиву JSON объектов “data”. В функцию “forEach” передается специальная функция, которая содержит три аргумента.
Первый аргумент “item” содержит текущий итерируемый экземпляр JSON.
Второй аргумент “i” содержит позицию итератора и имеет тип Number.
Третий аргумент “data” содержит исходный массив объектов JSON, по которым проводится итерация.
На 10 строке мы задаем условие поиска пользователя по его имени и паролю в списке всех пользователей полученной функцией “find”. В условии сравниваются имя и пароль, которые пришли в POST запросе на сервер, с именем и паролем, полученным от функции “find”.
На 12 строке, если пользователь был найден, мы присваиваем экземляру “res” JSON объект найденного пользователя.
На 15 строке мы обращаемся к экземпляру ответа “response”, вызываем на нем функцию “json”, которая принимает данные и возвращает ответ на клиент в JSON формате. В аргумент данного метода мы передаем или экземпляр найденного пользователя, или экземпляр ошибки, что пользователь не найден и авторизация не удалась.
На 18 строке мы экспортируем из модуля экземпляр маршрутизации “router”.
Откройте модуль “index.js”. Заполните его в соответствии с содержимым ниже:
На 1 строке подключаем модуль “express” и создаем его экземпляр с именем “express”.
На 2 строке создаем экземпляр маршрутизатора запросов с именем “router”.
На 3 строке строим маршрут типа “http://localhost:3000/index/”, доступный через HTTP глагол GET.
На 4 строке, на экземпляр ответа вызываем функцию “render”. Данная функция возьмет представление, указанное в первом аргументе функции и вернет его на сторону клиента. Вторым аргументом задается словарь, в который можно добавить свойства со значениями, к которым можно будет обращаться со стороны представления.
На 6 строке мы экспортируем из модуля экземпляр маршрутизации “router”.
Откройте модуль “index.ejs”. Заполните его в соответствии с содержимым ниже:
Библиотека Express JS позволяет нам обращаться к свойствам, которые мы указали во втором аргументе метода “render” путем добавления следующей конструкции “<%= Название_Свойства %>”. На этапе отрисовки страницы данные конструкции будут заменены на значение указанного свойства.
Откройте модуль “products.js”, заполните его в соответствии с содержимым ниже:
На 1 строке подключаем модуль “express” и создаем его экземпляр с именем “express”.
На 2 строке создаем экземпляр маршрутизатора запросов с именем “router”.
На 3 строке подключаем модуль “Product.js” и создаем его экземпляр с именем “Product”.
На 4 строке строим маршрут типа “http://localhost:3000/products/”. Данный маршрут будет доступен по HTTP глаголу GET.
На 5 строке мы вызываем на экземпляре “Product” функцию “find”. Внутри функции мы проверяем, были ли ошибки, и возвращаем в ответе JSON массив со списком всех товаров.
На 10 строке строим маршрут типа “http://localhost:3000/products/”. Данный маршрут будет доступен по HTTP глаголу POST.
На 11 строке мы вызываем на экземпляре “Product” функцию “create”. Внутри функции мы проверяем, были ли ошибки, и возвращаем в ответе JSON объект успешно созданного товара.
На 16 строке строим маршрут типа “http://localhost:3000/products/{_id}” (например, “http://localhost:3000/products/789w66s2322kks4676s” ). Данный маршрут будет доступен по HTTP глаголу GET.
На 17 строке мы вызываем на экземпляре “Product” функцию “findById”. Из названия функции ясно, что функция выполняет поиск по идентификатору товара. Для поиска используется скрытое поле “_id” в модели “Product”, объявленной в модуле “Product.js”. Внутри функции мы проверяем, были ли ошибки, и возвращаем в ответе JSON объект успешно найденного товара.
На 23 строке строим маршрут типа “http://localhost:3000/products/{_id}” (например, “http://localhost:3000/products/789w66s2322kks4676s” ). Данный маршрут будет доступен по HTTP глаголу PUT.
На 24 строке мы вызываем на экземпляре “Product” функцию “findByIdAndUpdate”. Из названия функции ясно, что выполняется поиск товара по его идентификатору “_id”, затем, в случае если найден, обновляются все его поля, кроме скрытых полей. В ответе возвращается JSON объект успешно обновленного товара.
На 30 строке строим маршрут типа “http://localhost:3000/products/{_id}” (например, “http://localhost:3000/products/789w66s2322kks4676s” ). Данный маршрут будет доступен по HTTP глаголу DELETE.
На 31 строке мы вызываем на экземпляре “Product” функцию “findByIdAndRemove”. Из названия функции ясно, что выполняется поиск товара по его идентификатору “_id”, затем, в случае если найден, товар удаляется. В ответе возвращается удаленный JSON объект.
Откройте модуль “users.js”, заполните его в соответствии с содержимым ниже:
В модуле “users.js” я не вижу смысла расписывать подробно, что происходит, поскольку тут все то же самое, что и происходило в модуле “products.js”, рассмотренном выше. Разница только в том, что мы используем другую модель данных “User”. Опишу только доступные маршруты.
На 4 строке строим маршрут типа “http://localhost:3000/users/”. Данный маршрут будет доступен по HTTP глаголу GET.
На 10 строке строим маршрут типа “http://localhost:3000/users/”. Данный маршрут будет доступен по HTTP глаголу POST.
На 16 строке строим маршрут типа “http://localhost:3000/users/{_id}” (например, “http://localhost:3000/users/789w66s2322kks4676s” ). Данный маршрут будет доступен по HTTP глаголу GET.
На 23 строке строим маршрут типа “http://localhost:3000/users/{_id}” (например, “http://localhost:3000/users/789w66s2322kks4676s” ). Данный маршрут будет доступен по HTTP глаголу PUT.
На 30 строке строим маршрут типа “http://localhost:3000/users/{_id}” (например, “http://localhost:3000/users/789w66s2322kks4676s” ). Данный маршрут будет доступен по HTTP глаголу DELETE.
Откройте модуль “app.js”, обновите его в соответствии с содержимым ниже:
Конкретно в модуль “app.js” были внесены следующие изменения.
С 8 по 11 строку были подключены модули “index.js”, “users.js”, “products.js”, “auth.js”.
На 13 строке был подключен модуль “mongoose”.
На 14 строке мы задаем свойство “Promise” в значение “global.Promise”, чтобы начать обмениваться сообщениями с базой данной “Mongo DB”.
На 15 строке мы подключаемся к базе данных “Mongo DB” c названием “warehouse”, мы ее ранее создавали в приложении “Robomongo”. Источник данных “mongodb://localhost/warehouse” можно разбить так: “mongodb://” протокол взаимодействия (аналоги “http://”, “tcp://”, “file://”). “localhost” - это адрес машины, на которой хостится база данных. “warehouse” - имя базы данных.
На 16 строке метод “then” вызывается в случае успешного подключения к базе данных.
На 17 строке метод “catch” вызывается в случае сбоя подключения к базе данных.
С 33 по 36 строку мы задаем доступные глобальные маршруты, которые будет обрабатывать сервер. Надеюсь, все помнят разницу между сервером и сервисами, это не одно и то же.
Сервер - это просто приложение, которое внутри себя способно содержать различные ресурсы. Сервер может запускать внутри себя различные потоки для обработки данных.
Сервис - это функционал, который как раз запускается в отдельном потоке внутри сервера.
Сам по себе сервис без наличия приложения ,в котором его можно разместить, работать не будет. В случае с WebAPI сервером является Microsoft IIS или отдельно стоящее исполняемое приложение с функцией self хостинга.
Мы закончили написание сервера. Запустите демон “mongod” в терминале.
Запустите сервер. Вы увидите обновленное приветствие.
Я бы рекомендовал вам прослушать курс “Angular JS”, автор Дмитрий Охрименко. Это один из лучших курсов, которые я когда-либо слушал. После данного курса вы без особых проблем сможете сделать клиентскую часть для сервера на “Angular JS”.
Теперь давайте научимся тестировать наши REST сервисы. Тестировать сервисы можно и через Fiddler, но на macOS у него есть проблемы с отрисовкой и работой. Поэтому откройте браузер и перейдите по адресу.
“Postman” - это аналог “Fiddler”, доступный в качестве расширения для браузера “Google Chrome”.
После установки расширения “Postman” откройте его.
Выполним первый запрос к сервису “users” по HTTP глаголу GET.
Заполните поле адрес, выберите глагол “GET”, нажмите кнопку “Send”. Результат придет - пусто. Обратите внимание, что в терминале “WebStorm” тоже пишется логирование вызовов при обращения к сервисам.
Откройте приложение “Robomongo”, подключитесь к базе данных. Разверните папку “Collections” базы данных “warehouse”, выполните щелчок правой кнопкой мыши по таблице “users”, в контекстном меню выберите “View Documents”. В “Mongo DB” нет колонок, там есть всего одна колонка, в которой хранится JSON объект. Строки называются документами. Причем, в каждую строку одной таблицы можно класть абсолютно разный по структуре JSON объект. База данных позволяет такую операцию.
Видим, что данных нет, это не удивительно, ведь мы еще ничего не добавляли.
Давайте добавим. Перейдите в “Postman”, выберите глагол “POST”.
Выберите “Content-Type” - “x-www-form-urlencoded”. Внимание, через другие типы “form-data” “raw” работать не будет. Заданные свойства “userName”, “userPwd”, “userDesc” будут отправлены в запросе как JSON объект “{ userName: 'admin', userPwd: 'abc123!', userDesc: 'Administrator' }”. Нажмите кнопку “Send”. Придет ответ:
В ответе мы видим JSON объект модели “User”, созданной на сервере.
Перейдите в приложение “Robomongo”, выполните пункт контекстного меню “View Documents” на таблице “users”.
Отлично, у нас появился первый пользователь :)
Перейдите в “Postman”, выберите HTTP глагол “GET”. Нажмите кнопку “Send”. Вы увидите такой результат.
Обратите внимание на квадратные скобки, в ответе пришел массив JSON объектов, а не один объект.
Теперь давайте изменим пароль пользователю “admin”, на “12345678”. Нам понадобится идентификатор пользователя, выделите и скопируйте значение свойства “_id”.
Выберите HTTP глагол “PUT”. Обновите данные так, как показано ниже.
Обратите внимание на добавление идентификатора пользователя после основного маршрута “../users/”. Нажмите кнопку “Send”. В ответе получим старый JSON объект до внесения изменений.
Теперь для того, чтобы посмотреть измененный объект, воспользуемся сервисом , который возвращает пользователя по его идентификатору “_id”. Выберите HTTP глагол “GET”, обновите адрес, добавьте в конец адреса идентификатор пользователя. Нажмите кнопку “Send”. Получим такой результат.
Видим, что пароль пользователя был успешно обновлен и мы получили в ответе один JSON объект, а не массив пользователей.
Теперь попробуем удалить пользователя. Адрес оставьте тот же. Выберите HTTP глагол “DELETE” и нажмите кнопку “Send”.
Видим, что в ответе содержится JSON объект удаленного пользователя.
Теперь проверим, доступен ли пользователь после удаления. Адрес оставьте тот же. Выберите HTTP глагол “GET”, нажмите кнопку “Send”.
Видим, что пользователь действительно был удален. Также можете проверить это в приложении “Robomongo”.
Теперь приступим к тестированию сервиса “products”.
Получим список товаров.
Товаров нет. Добавим первый товар.
Обновим описание товара.
Получим обновленный товар по его идентификатору.
Удалим товар.
На этом мы завершаем урок.
К данной статье прикреплен архив с готовым сервером на NodeJS , в помощь учащимся :)
На следующем уроке мы:
выполним рефакторинг проекта “Warehouse” под “iOS”;
научимся пользоваться CollectionViewController;
научимся пользоваться библиотекой “Alamofire”, в конце урока будут доступны исходники полноценного рабочего приложения;
научимся сохранять объекты в настройки телефона и извлекать их;
реализуем функциональность для работы со всеми сервисами, созданными в данном уроке;
добавим представление регистрации;
добавим представление редактирования пользователей.
Материалы к статье тут.