От COBOL для мэйнфреймов в объектно-ориентированную бездну: рев динозавра

Вы то, что вы едите

Кто-нибудь еще голоден? Я приближаюсь к концу третьего и последнего месяца программы наставничества ChiPy Spring, в рамках которой я изучаю Python (и многое другое), и кажется, что чем больше я копаюсь, тем больше я хочу потреблять! Мой набор навыков в этих современных технологиях растет с каждым днем, и я с удовольствием провожу время, изучая новые вещи и применяя их.

С момента публикации моего последнего блога я полностью погрузился в свой проект, и в результате у меня не только есть работающее веб-приложение, но я еще больше узнал о Python, а также о других известных технологиях, таких как облако AWS. Мой веб-сайт можно использовать для получения статистики в реальном времени с сервера MLB Gameday Data. Чтобы это произошло, я написал свою собственную логику для извлечения этих данных из огромной коллекции словарей JSON на их сервере, поскольку средний фанат не может получить доступ к API MLB. Это было скрытым благословением, поскольку я научился писать API на Python и как вызывать их с веб-сервера. Итак, давайте углубимся в занудные подробности! 🤓

Инфраструктура

Я решил разместить этот сайт в облаке AWS из-за важных событий в моей жизни, которые движутся в этом направлении, и, тем не менее, это определенно было бы еще одним отличным навыком в моем арсенале. AWS Elastic Beanstalk — это инструмент для развертывания и масштабирования веб-приложений, для которого требуется Python 3.4, поэтому виртуальная среда, которую я создал для разработки этого веб-сайта, должна была немного снизиться по сравнению с моей базовой установкой 3.6.

Я создал веб-приложение, используя фреймворк Python Flask. Это было сложно понять даже с помощью множества руководств по Flask, которые я нашел в Интернете. Я легко понял метод маршрутизации, но передать данные в/из формы и как правильно ссылаться на эти поля, особенно учитывая нюансы, присущие одной многоцелевой странице, которую я разработал, было сложно понять! Но после многих часов чтения, проб и ошибок, а иногда и F-bomb 💣, я победил, и данные хлынули на страницу, как вода над Ниагарским водопадом.

Быстрый доступ к данным

Изучив сервер MLB, я решил создать 3 файла, предоставляющих веб-приложению большую часть этой информации, а также направлять приложение к данным в реальном времени на сервере MLB по запросу. Два ключевых файла MLB управляли этой установкой…

Основное табло: Этот файл создается по одному экземпляру на каждый день, а глубоко внутри него находится расписание всех игр на этот день. Он содержит не только информацию об игре, но и каталог, в котором можно найти файлы для каждой игры! Это оказалось решающим в том, как я проектировал серверные и веб-процессы, которые будут управляться этими данными. #thankyouMLB

Ниже приведен лишь крошечный фрагмент файла Master Scoreboard от 20 июня, и я выделил область, относящуюся к игре Cubs vs Padres. Обратите внимание на ключевое слово словаря «game_data_directory», и его значение представляет собой длинное имя каталога, которое я использую для поиска файла boxscore для этой конкретной игры.

Boxscore: один из этих файлов существует для каждой игры, сыгранной в любой день, и находится в каталоге, специфичном для этой игры. Если команды играют с двойным заголовком, для каждой игры будут отдельные справочники и очки. Здесь я нашел статистику игроков, характерную для этой игры, а также их сезонную статистику. Единственное предостережение, которое действительно заставило меня создать мастер-файл игрока, заключалось в том, что в словаре Boxscore перечислены только игроки, которые играли в игру. Так что, если бы я хотел найти статистику Томми Ла Стеллы, а он не играл сегодня, мне пришлось бы искать в словарях Boxscore, возвращаясь в прошлое, день за днем, пока я не нашел бы последнюю игру, в которой он играл, чтобы я мог восстановить его правильная статистика сезона. Следовательно, необходимо создать мастер игрока. #uggghhh

Необходимые серверные процессы

Итак, основываясь на вышеизложенном, я написал внутренние процессы для создания и обновления трех файлов; файл ежедневного расписания, содержащий ссылки на все сегодняшние игры, и два основных файла (игроков и команд), которые используют файл расписания, чтобы найти путь к множеству данных. Эти файлы создаются из файлов boxscore в фоновом режиме в течение дня и стали исходными данными для большей части веб-приложения, поскольку большинство запросов относится к командным и сезонным данным. Только когда делается запрос на получение сегодняшней статистики, мне нужно снова получить доступ к boxscore на сервере MLB, чтобы получить эту самую последнюю статистику.

Кажется логичным, что такой процесс обновления мастер-файла нужно запускать только один раз в день, но благодаря тому, как данные обновляются на сервере Gameday, информация не доступна сразу. Информация об игре и составе просачивается и становится полной только за час до начала игры. Информация о расписании есть в начале дня, но каталоги могли быть еще не созданы, и даже если бы они были словарем Boxscore для каждой игры, возможно, еще не были созданы, и даже если бы они были готовы, составы могли бы не быть введены пока что. Это действительно требовало непрерывного процесса обновления в течение дня, чтобы у меня была информация, доступная для отображения в любое время. #сноваспасибоMLB

Я создал главные словари, используя JSON. Слева вход для Мэдисон Бамгарнер из Сан-Франциско Джайентс. Каждому игроку MLB присваивается уникальный «код», который, как правило, является его фамилией, если только несколько игроков не имеют одинаковую фамилию, и в этом случае часть имени добавляется, чтобы сделать их уникальными. Оттуда вы видите некоторую базовую информацию на следующем уровне вместе с двумя вложенными словарями, один для ударов и один для подачи.

Веб-приложение

При использовании Flask я смоделировал сценарии на основе того, что узнал из учебника Mega Flask. Существует веб-сервер, который ожидает HTTP-запросов от внешнего порта и направляет каждый запрос внутри в определенное место в основном модуле. Это было здорово, так как я мог легко увидеть, как действия, выполняемые на веб-странице (щелчок, отправка и т. д.), перенаправляются в соответствующую функцию для обработки запроса и, при необходимости, перенаправляются в другое место в модуле, подходящее для следующей части. запрос. Ниже приведен снимок маршрутизации и кода для страниц Home и Display By Team.

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

По пути на форум API произошел забавный случай. Я обнаружил, что независимо от того, какой тип данных я возвращал из API, мне приходилось сначала декодировать его, преобразовывая результат из строки байтов в строку символов (юникод). Затем я мог бы перезагрузить строку в словарь JSON, чтобы передать свои формы… это то, что API передал обратно вызывающему модулю в первую очередь. 😑

Все возвращается как тип данных Byte String. В конце концов, не составило большого труда добавить еще две строки магии Python для декодирования данных и перезагрузки словаря, но представьте себе мое разочарование, поскольку ни в одном руководстве и блоге, которые я читал, не упоминалась эта важная небольшая часть информации! IPython был моим спасением от этой и многих других проблем, с которыми мне пришлось столкнуться.

Привет, Web App Junction, в чем твоя функция?

Проще говоря, веб-сайт представляет собой механизм для получения и отображения статистики игроков MLB с помощью предопределенных методов, каждый из которых ведет пользователя по немного отличающемуся пути к нужным данным. Оба пути ведут к отображению списка игроков вместе с их статистикой за сезон. Если в этот момент выбран игрок, система извлечет и отобразит самую последнюю статистику из сегодняшнего файла boxscore.

По командам. Нажмите кнопку «По командам», и все 30 команд MLB будут показаны в алфавитном порядке вместе с их рекордами, сегодняшним соперником и местным временем, в которое они играют (если есть двойной заголовок). Затем нажмите на команду и всех игроков этой команды, и они будут отображены, сгруппированы по категориям «Удары» и «Питчи» и отсортированы по фамилиям в каждой категории с соответствующей статистикой.

По фамилии: нажмите кнопку «По фамилии». Откроется окно для ввода части фамилии игрока (необходимо минимум 1 буква). Нажмите «Поиск по имени», и статистика сезона для любого игрока, чья фамилия соответствует введенному начальному образцу, будет отображаться, сгруппирована по категориям ударов и подачи и отсортирована по фамилии в каждой категории с соответствующей статистикой.

Независимо от метода, используемого для отображения сезонной статистики для списка игроков, сегодняшняя статистика по уже завершенным или текущим играм находится всего в одном клике. Я написал очень классный HTML-код, чтобы выделить строку игрока, и сделал ее кликабельной, чтобы отправить запрос, чтобы увидеть сегодняшнюю статистику. Я могу очень быстро получить данные в реальном времени, так как выбранный игрок имеет связанный код команды, который указывает на запись этой команды в главном файле команды, в котором хранятся каталоги для сегодняшних игр, где я найду файл boxscore, содержащий сегодняшние статистика. Небольшая предварительная работа по проектированию может иметь большое значение для разработки эффективных систем.

Список наблюдения: это эпическая функция, которую я надеюсь завершить к большому танцу 13 июля. С помощью этой функции вы выбираете игроков, за которыми нужно следить, вводите свой номер телефона, и каждый раз, когда они совершают хоум-ран, система будет отправлять вам текстовые сообщения. Этот процесс будет использовать еще один словарь MLB, называемый журналом игровых событий, поскольку он сканирует хоум-раны, выбитые вашими любимыми игроками. Слава богу, мы только что получили кредит в размере 20 долларов от нашего великого спонсора Twilio, чтобы получить 2500 бесплатных сообщений! Теперь, когда у нас есть лишняя неделя, я надеюсь, что смогу использовать эти 2500 сообщений с пользой!

Вот ссылка на папку проекта в моей учетной записи GitHub. Не стесняйтесь просматривать и обращаться с любыми вопросами, имейте в виду, что сайт все еще находится в разработке, но он чертовски близок к завершению!



Я немного отвлекся…

В понедельник вечером я сидел на левой трибуне на стадионе «Ригли Филд» и смотрел игру «Кабс» вместе с моей дочерью Эшли. Воскресенье было Днем отца, и мы продолжили празднование в понедельник, который мы назвали Днем отца. Было возвращение героев нашего родного города в конце игры и драма 9-го иннинга, и Кабс удержались, чтобы обыграть Падрес, что принесло много радости толпе Мадвилля. Но во время игры, когда я не участвовал в разговорах и не участвовал в сумасшедших скандированиях с Bleacher Bums, в глубине моего разума решалась проблема в перерывах между иннингами.

Ранее в тот же день я увидел сообщение о проблеме, опубликованной в новом слабом канале (#code-talk), которая возникла на каком-то курсе MIT, и это казалось забавным вызовом. Я не мог устоять перед искушением разобраться в этом, так как люблю решать проблемы. Почти сразу же я понял, что это можно легко решить с помощью мощной техники, называемой рекурсией, и сделал несколько заметок. Моя дочь взглянула на то, что я писал в блокноте своего телефона, и спросила: «Что это, черт возьми?» На что я ответил: «Ну… это Python!»

Не спрашивайте меня, почему, но мой разум просто делает эти вещи, и когда он приближается к пониманию чего-то, он продолжает перебирать идеи на заднем плане, пока я не приду к решению. Какое это имеет отношение к моему веб-приложению? Ничего страшного, но в предыдущих двух блогах я сравнивал мир COBOL для мейнфреймов, из которого пришел этот динозавр, с миром Python/Object Oriented, по которому я сейчас путешествую, и собираюсь сделать то же самое снова здесь. Однако на этот раз я собираюсь сравнить код и показать вам решения, которые я написал как на Python, так и на COBOL, чтобы вы могли увидеть различия.

Сегодняшняя битва за титул, Python против COBOL!

Проблема заключалась в следующем: используя строку «azcbobobegghakl» в качестве входных данных, написать код Python для поиска самой длинной строки символов в порядке возрастания алфавита и подсчета связей. Буквы не обязательно должны быть последовательными, просто по порядку, и если одна и та же буква повторяется рядом друг с другом, это считается порядком. Учитывая процитированную входную строку, правильный ответ — beggh.

Во-первых, эпическое решение Python…

Обратите внимание на использование рекурсивных функций и на то, как они вызывают сами себя, чтобы сократить просматриваемую в данный момент строку до тех пор, пока в ней не закончатся буквы. Функция search_next_letter_in_s просматривает каждую букву в s (броское имя, а?) по одной и вызывает search_rest_of_s для просмотра остальных s, чтобы найти самую длинную строку в алфавитном порядке, начиная с этой точки.

Одна интересная вещь, которую следует отметить в этом решении, заключается в том, что для управления этим процессом не использовались циклы for или while. Это был самоуправляемый цикл, основанный только на рекурсии. Кроме того, не выполнялись никакие математические операции для манипулирования индексами, указывающими на текущий срез в проверяемой строке. На самом деле единственной операцией, которая что-то добавила, была конкатенация следующей буквы в s в строку current_long. Вы можете изменить string s на что угодно, даже на одну букву или на null, и это все равно работает!

И вот момент, которого вы все ждали… решение COBOL!

То, что вы видите слева, — это лишь предисловие к фактической логике. В COBOL мы должны сообщить программе, что она работает на архитектуре IBM 370 (мейнфрейм IBM 370 был создан в 1970 году и с тех пор претерпел значительные улучшения). Мы также должны определить все переменные, используемые в программе, их размеры, типы данных и любые начальные значения. Перед тем, как начнется настоящая работа, предстоит проделать большую работу, и это всего лишь крошечный пример!

Итак, теперь собственно логика решения проблемы…

Здесь циклов достаточно, тогда как в Python я мог кодировать без них, не то чтобы в этом что-то не так. Я не мог использовать рекурсию… ну, я мог, но позвольте мне сказать вам, сколько работы это повлечет за собой.

Во-первых, мне пришлось бы написать еще две программы: одну для абзаца, связанного с s, и одну для остальных s. Программы будут вызывать себя так же, как эквивалентные функции Python, которые я написал. Каждая программа потребует повторения всех скучных вещей, которые сообщают COBOL о среде IBM 370 и других интересных вещах, которые она хочет знать.

Далее мне нужно определить, что мы называем коммуникационной зоной (коммуникационной зоной). Здесь вы определяете все поля, которые передаются туда и обратно между двумя программами, и чтобы согласиться с этим, мне также пришлось бы закодировать раздел Linkage, в котором находится определение области связи (прямо перед разделом процедур). В соответствии с этими изменениями операторы выполнения, которые вы видите, изменятся на операторы вызова подпрограммы, которые должны будут указывать область связи, передаваемую другой программе.

Отложив в сторону понятие рекурсии COBOL и просто взглянув на два решения, которые я создал, какой язык вы бы выбрали для разработки собственного решения? Оба работают и дают правильные результаты. Но просто взглянув на количество строк кода, сама логика COBOL на 50% длиннее, чем решение Python, и к тому же нужно добавить эти скучные вещи.

Победитель техническим нокаутом…Python!!

Будьте уверены, что при проведении этого сравнения ни один динозавр не пострадал!

Какой путь вверх?

Предстоит еще поработать, чтобы этот сайт правильно работал в облаке и доработал некоторые дополнительные функции, и у меня осталось три недели, чтобы это сделать. Однако я полон решимости и уверен, что очень скоро вы увидите надежное веб-приложение, предоставляющее данные MLB в реальном времени.

Я получил удовольствие от этой программы наставничества и многому научился, и я всегда благодарен группе пользователей ChiPy, ее членам и, прежде всего, моему наставнику Аллану. Спасибо за то, что направили меня по прекрасному пути, на котором я многому научился, и за то, что мирились с шквалом вопросов и временами с небольшим упрямством. #thankyouAllan!!

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

Я не знаю, куда этот новый путь в конечном итоге приведет этого динозавра, но времена меняются, и дела, безусловно, улучшаются!