Примеры кода с летней школы по Node.js и JavaScript в КПИ

  • Tutorial

Товарищи инженеры, докладываю вам об успехах в подготовке научно-технических кадров в области программной инженерии на Факультете ИВТ в Киевском политехническом институте и публикую интересные примеры кода, которые были написаны для учебного курса, но будут, надеюсь, интересны и с практической точки зрения. Идея, внедрить JavaScript и Node.js в учебный процесс, вызревала у меня уже несколько лет. Но для освоения базовых вещей в программировании мне больше нравится C, чтобы люди прочувствовали машину, научились контролировать себя и свой код. А вот для прикладных задач, в которых уровень абстракции C уже не достаточно иллюстративен, мультипарадигменный и гибкий JavaScript прижился. При помощи мощного и простого API Node.js можно писать концептуальный код прямо на паре. Кроме того, знания JavaScript обязательно пригодятся на практике любому инженеру, работающему в ИТ. Часть кода, разработанного студентами курса, уже попала в серьезные Open Source проекты и это прекрасная практика, которую может повторить каждый, ведь лабораторные работы мы постепенно выкладываем на github и будем делать это и дальше, снабжая их методическими указаниями и не заботясь о том, что студенты будут списывать из форков, ведь все это нужно в первую очередь им самим. Эти материалы были использованы при подготовке порядка 300 студентов политехнического ВУЗа за 2015-2016 учебный год. Примеры я еще раз разложу по полочкам на летней школе, которая проходит с 9 по 26 августа 2016 года в Киеве, и расписание которой можно найти тут. Итак, переходим к самым показательным примерам кода.


Пример №1. Живые таблицы


Написание нечто на подобие живых таблиц Google Spreadsheets из гуглдоксов, может вдохновить даже двоечника. Пусть это будет маленькая электронная таблица 6x5, но в нее может зайти несколько человек и введенные ими данные будут синхронизироваться по сети в реальном времени. Это наглядно, эффектно и применимо на практике. Кроме того, в этом задании скрыты дополнительные темы, применение WebSocket и EventEmitter, написать его простую реализацию самостоятельно, расширить возможности EventEmitter для подписки на все события. Основная задача этой работы, рассчитанной на 1 лекцию и 2 практики, это освоить событийную реактивную модель вычислений, вместо прохода по циклу и трансляцию событий по сети.


Начинать можно уже не с нуля, базовый код сервера 41 строка, и 53 строки клиент написан и выложен вместе с заданием в гитхабе: https://github.com/HowProgrammingWorks/EventDrivenProgramming


Пример №2. Распределенные вычисления


Как увлечь студентов распределенными вычислениями? Я думаю, что им просто нужно дать что-то простое, что они смогут реализовать за одну-две пары. Ни кто, конечно, в здравом уме не будет писать больших вычислительных задач на Node.js, но он очень краток и показателен в том смысле, что JavaScript имеет однопоточную модель исполнения. Мы можем наглядно распараллелить вычисления, переведя их в асинхронную парадигму и распределив между несколькими процессами. Для этого предлагается перейти от циклов к итераторам. В этом случае исчезают переменные циклов и состояние, т.е. исходный набор данных уже можно резать и передавать в разные процессы. Это подходит для задач, в которых последовательность обработки элементов набора данных не важна, а таких задач очень много. Кроме того, итераторы можно переопределить, перехватить или написать свои. Мы можем реализовать межпроцессовое взаимодействие и сетевой обмен, скрыв это за абстракцией итератора. Прикладной код не изменится, только реализация итератора будет резать задачу на части, хранить у себя индексы частей, а потом, при получении результатов (пусть даже в другом порядке), их можно будет склеить в нужной последовательности.


Начинать тоже можно не с нуля, есть заготовки кода на гитхабе https://github.com/HowProgrammingWorks/InterProcessCommunication содержащие два варианта обмена между процессами: через IPC (встроенный в операционную систему и имеющий обертку в Node.js API) и через TCP сокеты. Последний можно применять не только для распараллеливания в пределах одного сервера, но и для построения кластера из нескольких многоядерных серверов.


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


Пример №3. Песочницы, инверсия управления и внедрение зависимостей


Еще одна важная тема, это экранирование прикладного кода в песочницах. В этом смысле Node.js дает нам доступ к API виртуальной машины V8 и это позволяет создавать контексты исполнения кода динамически. Песочницы имеют свой глобальный контекст и совершенно не имеют доступа к главному глобальному контексту приложения, если мы специально не пробросим в них ссылки на те или иные объекты. Благодаря этому мы можем продемонстрировать принципы инверсии управления и внедрения зависимостей для модулей, а не только для классов. Мы можем взять ссылку на объект или функцию из одной песочницы, и внедрить ее в другую песочницу. Можем обернуть любой API в песочнице, добавив в его поведение логирование, замеры скорости, распределенные вычисления, функции безопасности и что угодно. Песочницы, это одна из самых мощных возможностей ноды, но, к сожалению, пока мало используемая в прикладных приложениях.


Вообще говоря, управление зависимостями в ноде из коробки такое себе, все делается через DL (dependency lookup), реализацией которого и является пресловутый require. Это способ, при котором модули сами подгружают в свой контекст другие модули, указывая полный путь к файлу или имя модуля в репозитории npm. При этом, подгружаемые модули получают полный доступ к глобальному контексту приложения и могут изменить в нем что угодно, например, удалит setTimeout, переопределить метод Array.prototype.forEach() или заменить require своей функцией. Вообще, библиотеки JavaScript часто модифицируют базовые классы языка и это приводит к конфликтам кода. От этого нет спасения, кроме как запускать конфликтующий код в песочницах и реализовать экранирование, а зависимости внедрять из основного приложения, создавая ссылки на них в глобальном контексте песочниц.


Лучше всего перейти к внешнему декларативному описанию зависимостей, на подобие того, что мы имеем в package.json. Но require в ноде дублирует в императивном стиле, то декларативное описание, которое содержится в package.json. В больших проектах часто случается, что два разных компонента приложения зависят от разных версий одной библиотеки (это ужасно конечно, но как есть), а в package.json можно описать только одну. Оформлять все эти компоненты как отдельные npm пакеты и подымать свой npm сервер или выкладывать их в приватный репозиторий, можно конечно. Но значительно красивее решить сразу две задачи при помощи песочниц и внедрения зависимостей. Главный модуль может считать файл описания зависимостей и подгрузить нужные версии зависимостей в нужные песочницы, одновременно защищая их контексты.


Ссылка на репозиторий https://github.com/HowProgrammingWorks/InterProcessCommunication и в нем есть 3 папки:


  • sandboxedModule — это про использование песочниц
  • interfaceWrapper — про обертку интерфейсов
  • dependencyInjection — про внедрение зависимостей

Ссылки



Заключение


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

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 18

    –6

    JavaScript это, наверное, вредный язык для учебы в институте. Почему, например, не TypeScript? Там хоть компилятор будет бить по рукам, за то, что студенты пишут плохие программы. Да и более академично получится

      +4
      JavaScript это язык, на котором очень просто написать плохой код, он почти такой же опасный, как С. Но студенты должны учиться контролировать себя и свой код, пока они у меня учатся, я и мои асистенты будут бить их по рукам вместо компилятора. А после меня они или будут писать приличный код или будут отчислены.
        +2
        Тогда вам стоит задуматься о переходе к ассемблеру или к brainfuck-у на худой конец и использовании розг в учебном процессе.
          +2
          Мы собираемся поднять этот вопрос на ученом совете. Суровость же наказания за говнокод, будем компенсировать величиной поощрения за код приличный и успехи, лучшие студенты получили ценные призы, денежное поощрение, отличительные знаки и хорошую работу.
            +3
            Думаю лучшие студенты и так получили свою главную награду — перестали говнокодить :) Если честно, я дико рад за студентов и за предоставленную им возможность. Так держать!)
              +2
              Вот это вы точно правы!
              На самом деле думаю, чтобы не писать говнокод нужен хороший пример — хорошие листинги и объяснения к ним (естественно на уровне знаний, не более).
                0
                Хороший учитель — тоже хороший пример. Привитую изначально культуру написания кода изменить потом будет непросто…
        +2
        eslint в помощь
        +1
        Очень интересное мероприятие. Хотел поучаствовать, но не вышло. Спасибо за материалы!
          0
          Может вопрос и банален, но я не смог найти ответ. Собственно платные или бесплатные лекции?
            0
            Лекции бесплатные.
            0
            А почему нету тестов?
            0
            Эх, видео бы Ваших лекций :)
              +1
              Я думаю сделать скринкасты или аудиозапись со студийного микрофона. Видео из аудитории с 170 людьми — это очень шумно и сумбурно. Надеюсь найти на это время и наложить звук потом на слайды.
                0
                Такой материал был бы очень востребован. Спасибо за Ваши труды.
                  0
                  Думаю, эти скринкасты не только ваши студенты оценят, но и многие начинающие, как например я))
                0
                Повезло же вашем студентам. Многое бы отдал за такие курсы в свое время в универе.
                Так держать!

                Only users with full accounts can post comments. Log in, please.