Skip to content

Статья написана в образовательных целях на онлайн-курсе для веб-разработчиков

Notifications You must be signed in to change notification settings

dvmn-tasks/input_output

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 

Repository files navigation

Отделяйте ввод/вывод от обработки

Ключевой критерий качества кода — это стоимость внесения в него изменений. Если изменять программу сложно, то проект медленно развивается, несет убытки и, в конечном счете погибает. С другой стороны, бесконечно расширяемый и безгранично гибкий код — это как сферический конь в вакууме. Теоретически возможен, но практической ценности не несет.

Один из часто встречающихся и оправданных приемов — это отделение обработки данных от процесса ввода/вывода. Рассмотрим несколько примеров.

Пример. Подбор онлайн-курса

По условию задачи нужно скачать из сети данные об онлайн-курсах, выбрать из них лучшие и сохранить результат в xlsx файл. Вот фрагмент кода:

def get_courses_list(courses_url): html = fetch_html(courses_url) if html: # .... parsing logic return courses_list else: print("can't load list of courses") exit() Теперь примерим на себя роль провидца и подумаем какой функционал потребуется через месяц:

В случае сетевой ошибки взять паузу в 10 секунд и повторить попытку, затем подождать еще 30 секунд и так далее. В случае если адрес недоступен - постучаться по другому url в зеркало сайта. В случае ошибки сделать запись в лог и взять данные из ранее подготовленного кеша. Как все это сделать когда def get_courses_list сама завершает программу ?! От вызова exit() надо отказаться. Можно выбросить исключение и таким образом сообщить о проблеме внешнему коду, пускай там разбираются.

Вызов print тоже стоит вынести из тела функции наружу. В рассмотренных сценариях вывод в консоль зависит от общей логики загрузки данных и многократных вызовов def get_courses_list.

Что еще может потребоваться в скором будущем?

Отладить и покрыть тестами парсер HTML страницы. Ускорить работу скрипта, хранить ранее скачанные страницы в кеше на жестком диске. Ага, значит вызывать fetch_html() внутри def get_courses_list не такая уж хорошая идея. Жить будет легче если передать в def get_courses_list строку с HTML разметкой вместо courses_url. Вуаля, мы решили проблемы еще до их появления на горизонте!

Пойдем дальше. Код другой функции:

def get_course_info(html): # ... parsing logic

rating = soup.find_all('div', attrs={'class': 'ratings-text'})
if rating:  # check if rating is not empty list
    rating = rating[0].contents[0].text
else:
    # we wanna be user-friendly, with nice output to xlsx
    rating = "No rating yet"

# .... parsing logic

return course_data

Что может произойти с кодом дальше?

Если рейтинга нет — надо искать его на другом сайте. В xlsx указывать не просто отсутствие рейтинга, а еще на каких сайтах искал. Отчет о курсах без рейтинга выгружать в дополнительную вкладку xlsx, чтобы удобнее было руками проверять. Для всего этого нужно уметь отличать от прочих ситуацию "рейтинг неизвестен". В Python для этих целей предусмотрено значение rating = None. А строку "No rating yet" можно переместить туда где данные подготавливаются к выводу в xlsx.

Та же функция, часть вторая, последняя:

def get_course_info(html): # ... more parsing logic is here

# number prefix is usefull for simple sorting data before output to xlsx
return {
    '1_title': title,
    '2_date': start_date,
    '3_language': language,
    '4_weeks': duration,
    "5_rating": rating
}

Сразу возникают вопросы. А если нужна еще одна выгрузка в формате csv, с другим порядком столбцов, как это сделать? Как заменить столбец 2_date на days_before_start ?

Кроме того, наперед известно, что пользовательский интерфейс — будь то вывод в консоль или запись в файл — меняется очень часто. Было бы удобно собрать все, что относится к форматированию вывода в одном месте. Например, всю логику выгрузки в xlsx поместить в def fill_xlsx(workbook, courses):, а вывод в консоль собрать внутри if name=='main':. Удастся избежать вычитывания и повторной отладки всей программы от начала до конца, ведь изменения локальны и изолированы.

Вместо заключения

В результате мы пришли к ситуации, когда логика обработки данных слабо зависит:

1)от источника данных; 2)от формата вывода в файл.

About

Статья написана в образовательных целях на онлайн-курсе для веб-разработчиков

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •