Пишем каркас приложения
Итак, накидывать функционал можно по-разному. Есть множество подходов. Например, есть TDD, Test Driven Development, согласно которому надо сначала написать много-много тестов, они все сначала падают с ошибками, а потом просто постепенно мы пишем код, который заставляет эти тесты постепенно работать.
Мы по TDD сейчас не пойдём и тесты писать не будем, но в целом можете иметь в голове такой подход. Мы начнём постепенно с реализации, думая каждый раз, в каком слое должна лежать реализуемая сейчас функция или класс.
Файл weather
:
#!/usr/bin/env python3.10
from coordinates import get_gps_coordinates
from weather_api_service import get_weather
from weather_formatter import format_weather
def main():
coordinates = get_gps_coordinates()
weather = get_weather(coordinates)
print(format_weather(weather))
if __name__ == "__main__":
main()
То есть фактическая реализация логики будет инкапсулирована, то есть заключена в отдельные Python-модули coordinates
, weather_api_service
и weather_formatter
, а модуль weather
будет просто точкой входа в приложение, запускающей логику.
Обратите внимание — при таком подходе у нас изначально не получится ситуации, что вся логика написана в одной каше, например, вообще без функций или в одной длинной километровой функции. Мы подумали о слоях нашего приложения, для каждого слоя создали отдельное место, в нашем случае Python-модуль, но впоследствии можно расширить до Python-пакета, и теперь будем создавать функции, в которые ляжет бизнес-логика нашего приложения.
Файл coordinates.py
:
def get_gps_coordinates():
"""Returns current coordinates using MacBook GPS"""
pass
И вот тут было бы неплохо подумать, какой формат данных вернёт эта чудесная функция. Она очевидно должна вернуть координаты. Координаты это широта и долгота, то есть два числа. Какие есть варианты?
Самый простой вариант — просто tuple с двумя float числами:
def get_gps_coordinates() -> tuple[float, float]:
"""Returns current coordinates using MacBook GPS"""
pass
Так, хорошо... А широта это нулевой элемент кортежа, а долгота это первый элемент, да? Или наоборот? Насколько хорошо, что приходится додумывать или читать внутренний код функции, чтобы понять, что она возвращает? В этом нет ничего хорошего. Надо явным образом прописать тип, чтобы разночтений не было и все типы были понятны по сигнатуре функции.