Pull to refresh
VK
Building the Internet

Курс «Языки веб-программирования» (на основе Ruby) от МГТУ им. Н. Э. Баумана на канале Технострим

Reading time14 min
Views21K


В этой статье мы расскажем о курсе «Языки веб-программирования», который читается на кафедре «Компьютерные системы и сети» (ИУ-6) МГТУ им. Н.Э. Баумана. Примеры приводятся на Ruby, а сам курс и представляет собой 16 видеолекций, доступных бесплатно на канале Технострим. В «Бауманке» курс читается для студентов второго курса, уже знакомых с высокоуровневыми языками программирования, такими как Pascal, C++ или Java. Основной акцент делается на системное понимание технологий, используемых в веб-программировании, а не на глубину освоения именно технологий Ruby. Поэтому курс также будет полезен слушателям, имеющим отрывочные знания о веб-технологиях на любых языках.

Содержание


  1. О курсе «Языки веб-программирования»

  2. Содержание лекций

  3. Как создать курс для вуза
  4. Почему Ruby?
  5. Почему Ruby не популярен?
  6. Резюме

Языки веб-программирования


Почему курс называется «Языки веб-программирования»? Ответ очень прост. Как 30 лет назад, когда Интернет только зарождался, так и сейчас нет возможности использовать один язык программирования.

  • Языки разметки — это HTML и CSS.
  • Языки конфигурирования и обмена данными — JSON, XML, YAML.
  • Браузерное программирование — Javascript (Typescript, Coffeescript...).
  • Серверное программирование — Ruby, PHP, Perl, Java, Javascript…

Чтобы понять веб-программирование даже в минимальном объёме требуется знать 4-5 языков разметки и программирования (хотя границы между ними сейчас уже размыты).

Цель курса


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

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

Автор курса


Главный разработчик курса — кандидат технических наук, доцент кафедры «Компьютерные системы и сети» МГТУ им. Н. Э. Баумана Самарев Роман Станиславович. Программист с более чем 20-летним опытом (C++, C, Java, Perl, PHP, Ruby и др. для Windows, Linux, Embedded Linux, MacOS), руководитель программных разработок, исследователь в области СУБД, обработки данных и больших данных, работал в России, в Германии и в США.

Длительность и формат


Полный курс включает 192 академических часа: 16 лекций по 2 часа, 8 семинаров по 2 часа, 48 часов на 12 лабораторных работ. Остальное время выделено на самостоятельную подготовку. Видеоматериалы же включают только лекционную часть. Желающим глубже погрузиться в тему курса, материалы лабораторных работ и семинаров придется осваивать самостоятельно. Все вопросы можно задавать преподавателю: samarev@acm.org.

Результаты


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

Содержание курса


Лекции 1-2. Введение

  • Введение в веб-программирование с точки зрения базовой архитектуры.
  • Минимальные сведения о языках разметки и таблицах стилей.
  • Минимальное введение в Javascript.



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

Лекции 3-5. Ruby

Следующие три лекции посвящены Ruby, поскольку именно технологии на этом языке Ruby положены в основу курса. Лекции включают:

  • Основы языка Ruby.
  • Необходимые сведения о структуре типов и объектной модели.
  • Функциональный стиль.




Лекция 6. Принципы построения веб-приложений

  • Common Gateway Interface.


Кто-то скажет, что этот стандарт не актуален, но он лежит в основе всего современного веб-программирования. Поэтому любой веб-программист просто обязан знать, что это такое, и должен понимать, что простейшее веб-приложение — это всего лишь put 'Hello World'.

Лекция 7. Rack

  • Rack — промежуточный слой для большинства веб-фреймворков на Ruby.
  • Sinatra — распространенный фреймворк для создания простых приложений.
  • Пример создания приложения.


Лекция 8. Введение в Rails

  • Ключевые аспекты Rails-приложения.


Ruby on Rails — тот самый фреймворк, который сделал язык Ruby знаменитым и стал почти его синонимом. Это один из примеров глубоко проработанного фреймворка с концепцией Model-View-Controller, который послужил прототипом для создания множества других веб-фреймворков, включая Grails и Django. Отметим, что концепция Rails: генерировать как можно больше кода при помощи автоматических генераторов и меньше писать руками.

Лекция 9. Асинхронное взаимодействие

Большинство современных веб-приложений используют асинхронный метод, то есть запросы к серверу уходят в фоновом режиме для пользователя. Ответы отрабатываются где-то в глубине браузера. Что здесь надо знать?

  • Обменные форматы — XML и JSON.
  • Запуск асинхронного запроса из Javascript.
  • Концепция ненавязчивого Javascript применительно к Rails.


Лекция 10. Тестирование

Любые современные программы должны быть покрыты автоматическими тестами. Ruby предполагает использование модульных тестов. И, естественно, Rails предполагает, что любое действие должно быть покрыто тестами. Лекция включает следующие темы:

  • Тестирование различных аспектов веб-приложений.
  • Введение в языки предметной области (поскольку RSpec и Cucumber — те самые примеры «человечности» в тестах: программа тестирования должна быть понятна не только для программиста, который «заточен» под используемый язык, но и для нормального человека). Обратите внимание, что подход, использованный как в RSpec, так и в Cucumber, сейчас широко растиражирован в средствах тестирования для многих других языков программирования.
  • Средства типа SikuliX и Selenium, которые могут быть использованы для тестирования программ с графическим интерфейсом и браузерами соответственно.


Лекция 11. Технологии XML

  • Языки запросов типа Xpath, Xquery.
  • XSL и XSLT.


Казалось бы, какое это отношение всё это все имеет к веб-программированию? Но XML лежит в основе веб-технологий. То, что сейчас мы не используем XML в качестве обменного формата, вовсе не гарантирует, что через 5 лет мы опять не начнем это делать. До сих пор нет единого подхода к верификации данных в формате JSON. А в случае с XML схема разметки заложена самим языком.

Язык запросов Xpath — это, по сути, универсальный язык путевых запросов, который может быть использован для поиска любых элементов древовидных структур данных, куда входит и JSON.

Преобразования XSLT — это также еще один из способов трансформации документов XML, знание о котором позволит студентам не изобретать велосипеды в будущем, когда они столкнутся с ETL.

Лекция 12. ORM (Object-Relational Mapping)

Практически любой современный фреймворк для веб-программирования предоставляет какие-либо средства для объектно-реляционного преобразования. Студентам необходимо понимать:

  • для чего нужен такой механизм;
  • какие у него ограничения;
  • как им пользоваться на практике.

В данном случае всё рассматривается в контексте Ruby on Rails.


Лекция 13. Сессии, безопасность и всё, что с этим связано

  • Способ хранения состояния, основанный на cookies.
  • Типовые способы аутентификации.
  • Пример добавления авторизации в Rails.
  • Вопросы безопасности веб-приложений как таковых.


Лекция 14. Сервисы

  • Исторические аспекты.
  • Конкретные рекомендации по разработке и размещению собственных сервисов для Web.


Лекция 15. CMS (Content Management Systems)
В веб-программировании важно не только уметь написать приложение, но и понимать, нужно ли его писать. Эта лекция — демонстрация основных типов уже созданных веб-приложений, которые можно настроить под требования конкретного заказчика и, при необходимости, доработать.

  • Акцент на Ruby-средства.
  • Самые распространенные CMS, написанные на PHP.


Лекция 16. Размещение Ruby веб-приложений в Интернете

Рассматривается общая идеология веб-сервисов. Объясняются истоки появления этой архитектуры с обменным форматом XML и её дальнейшая модификация в Web-API с JSON и REST или GraphQL.

  • Веб-серверы.
  • Методы виртуализации.
  • Способы размещения приложения в Интернете.


Как создать курс для ВУЗа


Сложно создавать учебные курсы по темам, связанным с программированием, где технологии меняются каждые 5-10 лет. При создании курса для университета приходится балансировать между формированием практических навыков по конкретным языкам программирования и подачей теоретических основ, необходимых для понимания технологий как таковых. А кроме того, отличие университетского образования от учебных курсов заключается в системной подаче материала, что также накладывает ограничения на то, когда и в каком объеме может быть подан определенный материал.

В последние годы появилась тенденция записывать университетские лекции на видео и создавать видеокурсы. Курс «Языки веб-программирования» является первой такой официальной попыткой нашего ВУЗа. И на основе отзывов мы решим, как и в каком формате делать новые записи.

10 лет назад нужно было радикально обновить учебную программу, внедрив, в том числе, веб-программирование. На кафедре «Компьютерные системы и сети» на курсы, связанные с электроникой и проектированием ЭВМ, традиционно выделяют примерно столько же учебных часов, сколько и на программирование. Причем курсы по программированию включают в себя алгоритмическую подготовку на высокоуровневых языках Pascal, С, С++/Qt, подготовку на на различных ассемблерах, а также теорию языков программирования и компиляторы. И даже языки для программирования ПЛИС и специфического железа. То есть кафедра готовит универсальных специалистов, которые в дальнейшем сами выбирают специализацию.

Нам требовалось выявить перспективные веб-технологии, которые могут быть освоены за семестр, причем желательно, чтобы эти технологии могли быть спроецированы на другие языки программирования.

Почему Ruby?


Почему выбран Ruby? Выбор языков для веб-программирования достаточно богат. Помимо Ruby это PHP, Perl, Javascript, Java, Go и другие. Если же подходить с позиции высоконагруженных веб-приложений, то, отправляя сомневающихся в Web Framework Benchmarks, видим в первых рядах C++, Java, Rust, Ur, Go и пр. Ruby не является ни самым популярным для веб-разработки, ни самым быстрым для высоконагруженных решений. Однако у Ruby есть масса других достоинств, делающих его языком программирования, о котором должен иметь представление любой образованный программист.

Недавно Ruby отметил 25-летие, то есть это достаточно зрелый язык. Несмотря на то, что большинство упомянутых языков также перешагнули или близки к этому возрасту (Rust, Dart, Go пока «зеленые» по сравнению с ним), Ruby — один из немногих языков, сохраняющий обратную совместимость на протяжении этих лет.

В мире Ruby, можно сказать, не было революций и каких-то радикальных изменений. Он относится к изначально хорошо спроектированным языкам, базовые концепты которого дошли до сего дня без изменений. Претензии по производительности относились к старым версиям до 1.8.7, поддержка которых прекращена 10 лет назад. Современные версии каждый год демонстрируют кратный рост производительности. Претензии, что этот язык мало популярен, справедливы лишь для нашей страны. К сожалению, у нас крупные компании действительно незаслуженно обходят его стороной.

Почему Ruby хорош для университетского образования? Это чистый объектный язык. И поскольку он динамический, переопределить можно почти всё. Никаких простых типов в его модели нет (не будем здесь размышлять о системной реализации, речь только о модели). Любые данные — это объект. Код — это объект. То есть Ruby позволяет легко усвоить принципы объектно-ориентированного программирования. Кроме того, синтаксис языка достаточно прост и почти не имеет исключений. Любой код, написанный в программе, должен быть когда-то выполнен, причем не важно, где этот код написан — внутри объявления класса или снаружи. Что бы ни было написано, оно будет выполнено. Синтаксис Ruby очень гибкий, что делает его очень удобным для написания языков, ориентированных на предметную область (DSL/DSEL). Кроме того, базовый концепт Ruby — блок — это анонимная функция. Освоение этих принципов позволяет студентам легко овладеть функциональным программированием на чистых функциональных языках программирования.

И, скорее, декоративное достоинство Ruby — не нужно тратить время на объяснение обязательности форматирования кода отступами. Программа в любом случае четко размечена. Форматирование автоматически обеспечит rubocop, а писать правильно студенты научатся со временем.

Почему Ruby не популярен?


Почему же Ruby, обладая такими достоинствами, всё же не популярен и относится к языкам с высоким порогом вхождения?

Первое, что следует понимать: Ruby — это не очередной императивный язык программирования, на котором можно начать программировать за вечер, а за неделю постичь полностью. Это другой язык с другой философией.

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

Ruby часто критикуют за то, что одно и то же можно сделать десятком способов. Но в естественном языке мы имеем огромное количество синонимов, и именно выбор верного синонима делает нашу речь богатой. Так и в Ruby. Помимо того, что одни и те же действия можно совершить разными способами, на одни и те же методы существует множество синонимов, ассоциированных специальными методами alias и alias_method.

Простой пример ограниченности большинства других языков программирования. Допустим, есть массив products, и требуется определить, что он не пуст. В большинстве языков мы напишем что-то типа if (products.size() > 0)…. Но, придя в магазин, мы не спрашиваем продавца: «Если у вас больше нуля такого-то товара?». Мы задаем простой вопрос: «Есть ли у вас такой-то товар?». В Ruby надо использовать методы, выражающие смысл действия. Да, мы можем использовать проверку на «больше нуля», но естественный способ — спросить if products.any? То есть буквально: есть ли продукты? Отметим, что Ruby хорошо работает с Юникодом, поэтому при необходимости на базе этого языка можно создать специализированные языки с региональной адаптацией. Например, если требуется переопределить по-русски все имена классов и методов.  

Интересный, хоть и не совсем прямой пример: Bato: A Ruby port for Filipinos.

К вопросу об объектности языка: в Ruby четко разделяются переменные/константы и объекты. В силу динамической природы языка данные «живут» своей жизнью как объекты. Любой идентификатор представляет собой константу или переменную, которая всего лишь ссылается на объект. Непонимание этого принципа приводит к неожиданностям:

str1 = "Test"
str2 = str1
str1.sub! "Te", "La"
puts str2 # => "Last" ???? Мы же меняли str1, что случилось?..

Здесь мы всего лишь использовали модифицирующий метод объекта, ссылки на который хранили две переменные. Отмечу, что это не традиционный для Ruby способ изменения. Обычно объекты сохраняют неизменными, а изменения порождают новые объекты. Кроме того, использованный здесь метод sub! имеет суффикс — восклицательный знак, — что является принятой в Ruby схемой именования методов, которые изменяют сам объект. Без этого символа метод просто породит новый объект.

Еще одна особенность Ruby, которая очень часто ставит в тупик разработчиков, пришедших из других языков программирования: концепция «блока». Синтаксически блок выглядит так же, как и в других языках программирования, причем сразу в двух вариантах: {…} и do..end (не забывайте, что Ruby создан для человека, поэтому выбираем для лучшей читаемости скобки, если выражение однострочное, и слова, если строк много). Суть блока в Ruby — это код, который хранится как объект и может быть активирован вызовом yield. Прямой аналог в C и  C++ — функции обратного вызова. В Javascript — анонимная функция типа some_func('on_element_click', function(event) {…}).

Именно благодаря этой концепции Ruby является одним из наиболее лаконичных и выразительных языков программирования. Например, преобразование элементов массива в соответствии с функцией возведения в квадрат будет выглядеть так:

(1..5).map { |x| x * x } # => 1, 4, 9, 16, 25,

где { |x| x * x } — блок с объявленной локальной переменной x, то есть функция преобразования элементов массива. А метод, которому она передается, просто называется map (то есть «отобразить»). Причем не надо писать слово return, хотя это и возможно, потому что всё и так ясно (в Ruby результат последней операции всегда является возвращаемым значением). Причем код блока — это код, вызываемый автономно для каждого элемента массива. Именно поэтому бессмысленно пытаться заводить внутри блока переменные и надеяться, что их значение сохранится при обработке следующего элемента. Блок — это сохраненная функция обработки, и не более.

Если же мы хотим разобрать строку с числами, введенными с клавиатуры, достаточно написать:

gets.chomp.split.map(&:to_i)

То есть прочитать строку (gets), отбросить всякий мусор вроде символов перевода строк (chomp), разбить на слова (split), вызвать преобразование с функцией to_i (строго говоря, метода объектов типа «строка»). И ничего лишнего. Split знает, что в нормальном человеческом языке «разбить строку» означает разделить её по словам, где разделители — пробелы и знаки препинания. Map может быть использован в такой короткой форме с именем метода, который надо взять у объекта. Хотя можно было бы написать и полную форму map { |x| x.to_i }, или даже { |x| return x.to_i }. Но это не улучшает читаемость, поэтому можно оставить просто map(&:to_i).

Замечу, что концепция блока откровенно пронизывает Ruby. Даже код вида

class HelloWorld
  (1..3).each { puts 'Hi from class declaration!' }

  def hi
    puts 'Hello World!'
  end
end
HelloWorld.new.hi

выводит на экран:

Hi from class declaration!
Hi from class declaration!
Hi from class declaration!
Hello World!


Что здесь может показаться неожиданным? Цикл внутри объявления класса вывел сообщения. Потом получили сообщение из метода экземпляра этого класса. А секрет очень прост. Ruby — язык с регулярной моделью программирования. Типовой способ вызова любого метода с блоком:

method_with_block(args) do
...
end

Слова class и def в примере, по сути, являются именами методов, которым передаются аргументы HelloWorld, hi. Аргумент HelloWorld станет для нас константой-именем класса, а hi — именем метода. Остальная часть до слова end — это блок. А код блока активируется вызовом yield, после чего всё последовательно выполняется. То есть даже здесь практически нет разницы между вызовом обычного метода и объявлением методов, классов, модулей.

Также обратите внимание на активирующую конструкцию HelloWorld.new.hi. HelloWorld — константа — указывает на объект типа Class. У этого объекта есть метод new. Результатом вызова new является созданный объект типа HelloWorld, от которого вызываем метод hi. И даже здесь проявляется регулярность Ruby. Мы не пишем something = new HelloWorld, а просто вызываем метод конкретного объекта (Class, на который ссылается HelloWorld), который и порождает объект типа HelloWorld.

Непониманию языка способствуют и длинные цепочки вызовов:



Если вы знаете JavaScript или jQuery, то ничего особенно страшного здесь не видите. У тех же, кто пришел из C и C++, может возникнуть недоумение относительно количества точек. В Ruby применяется функциональное преобразование объекта. То есть вся эта цепочка — процесс преобразования строки, заключающийся в выделении слов, их преобразовании в числа, отборе только четных из них, возведении в квадрат и сложении результата.

Любой метод в Ruby порождает объект-значение. Исключений нет. Даже nil является объектом. Поскольку Ruby — динамический язык с автоматическим сборщиком мусора, нет необходимости заводить новые переменные. Промежуточные объекты будут удалены. То есть длинное выражение легко может быть разобрано на последовательность присвоения значений локальным переменным, которые последовательно вызывают соответствующие методы. Но зачем, если и так всё понятно?

В программах на Ruby крайне редко можно увидеть циклы типа for, while, loop. Они предусмотрены в синтаксисе, но почти не используются. Почему? Да потому, что не несут семантическую нагрузку.

Пример: в массиве товаров надо найти «булочку с маком». Для традиционных языков программирования можем воспользоваться примерно следующим Ruby-кодом:

products…# какой-то массив с объектами — товарами.
found_product = nil
for i in 0...products.size do
  if products[i].name == 'булочка с маком'
    found_product = products[i]
    break
  end
end

if  found_product != nil
  # Булочки нашли, делаем что-то полезное.
end

При этом нормальный Ruby-код выглядит как:

products… # какой-то массив с объектами-товарами
found_product = products.find { |product| product.name.eql? 'булочка с маком' }
unless found_product.nil?
# Булочки нашли, делаем что-то полезное.
end

То есть пишем буквально в одну строчку: товар найти по названию. И всё. Потому что реально нас интересует только отбор товара, а вовсе не индексы товаров и не их количество.

Пример из жизни: вы пришли в магазин и спросили несчастного продавца двумя способами: первый —  «Для всех товаров от нуля до 15143, если наименование товара равно булочка с маком, то дайте мне её»; второй — «Дайте мне булочку с маком». Вроде бы оба варианта синтаксически правильны, но естественен второй. Большинство программистов почему-то считают нормальным первый вариант. А Ruby-программисты — второй. И метод find здесь просто как один из заменителей цикла. Обращаю на это внимание, упреждая замечания, что в других языках тоже есть поиск по массиву с функцией отбора.

Так вот, хотя в Ruby есть синтаксические конструкции for, while и loop, их почти никто не использует, потому что есть конкретные методы: each, each_index, each_with_index, select, map, reduce, find, detect и многие другие, выражающие конкретный смысл — для каждого индекса, для каждого элемента и его индекса, отобрать, преобразовать, свернуть, найти и пр. И если надо получить индексы, мы будем использовать array.each_index. А если надо отобрать элементы, воспользуемся select. Акцент на естественность. Запрашиваем только то, что реально нужно сделать. Не нужен индекс — незачем его просить. Подробнее см. документацию по модулю Enumerable.

Резюме


Ruby — синтаксически простой, но гибкий язык с развитой объектной моделью, основной акцент которого — лаконичный, но хорошо воспринимаемый код, ориентированный на живого человека. Ruby присутствует по умолчанию в комплекте любой современной операционной системы (или может быть доустановлен в Windows). На этом языке написано огромное количество программ, существуют стабильные сообщества, готовые помочь советом или действием. Программы на Ruby — это базовые скрипты администрирования для Linux и MacOS (OpenSuSE/SuSE и brew.io соответственно), это математика и машинное обучение, это тесты (Rspec, Cucumber, Capybara...), это развертывание приложений (Puppet, Chef) и многое другое.

Если студенты будут знать Ruby, это существенно расширит их кругозор, позволит совершенно по-другому взглянуть на привычные вещи. Кроме того, после Ruby очень легко изучать другие скриптовые языки программирования, но вопрос: захочется ли их использовать.
Tags:
Hubs:
Total votes 24: ↑24 and ↓0+24
Comments18

Articles

Information

Website
vk.com
Registered
Founded
Employees
5,001–10,000 employees
Location
Россия
Representative
Миша Берггрен