Загрузка данных



1. Цель работы

Освоить методы анализа и моделирования программного продукта, научиться выявлять потоки данных в системе, сравнивать версии приложения и подготавливать материалы для последующего ревьюирования программного модуля.

---

2. Описание программного продукта

Название: MiniLedger (консольное приложение для учёта личных финансов).
Назначение: позволяет пользователю добавлять записи о доходах и расходах, просматривать список операций, фильтровать их по дате, категории и типу, а также получать итоговый отчёт (сумма доходов, расходов, баланс).
Версии:

· v1 – базовая реализация с минимальной валидацией, все данные хранятся в памяти в виде списка словарей.
· v2 – улучшенная версия с использованием dataclass, строгой валидацией ввода (тип операции, сумма > 0, корректный формат даты, непустые поля) и типизацией.

Обе версии являются консольными и не требуют авторизации.

---

3. Анализ предметной области

3.1 Назначение программы

· Решаемая задача: ведение личного бюджета – фиксация финансовых операций, их просмотр, фильтрация и подведение итогов.
· Целевая аудитория: физические лица, желающие контролировать свои доходы и расходы без использования сложных приложений.
· Контекст использования: домашний компьютер или учебная среда, где можно быстро запустить скрипт Python для разового или периодического учёта.

3.2 Пользователь системы

· Инициатор работы: пользователь, запускающий программу.
· Действия пользователя: выбор пунктов меню (1–4), ввод данных операции (тип, сумма, категория, дата, комментарий), задание критериев фильтрации.
· Авторизация: не требуется – приложение однопользовательское, данные хранятся только в оперативной памяти.

3.3 Входные данные

· Тип операции (строка: income или expense).
· Сумма (число с плавающей точкой, положительное).
· Категория (строка, например, «еда», «транспорт»).
· Дата (строка в формате YYYY-MM-DD).
· Комментарий (строка, может быть пустой).
· Для фильтрации: диапазон дат (две строки), категория, тип операции – каждое поле опционально.

3.4 Выходные данные

· Список всех операций (нумерованный, с датой, типом, суммой, категорией, комментарием).
· Отфильтрованный список операций (по тем же правилам вывода).
· Итоговый отчёт: сумма доходов, сумма расходов, баланс (доходы – расходы).
· Сообщения об ошибках при некорректном вводе.

3.5 Хранилище данных

· Где хранятся данные: в оперативной памяти – глобальный список ledger.
· Структура хранения:
  · Версия 1: список словарей, каждый словарь содержит ключи type, amount, category, date, comment.
  · Версия 2: список объектов класса Transaction (dataclass с полями tx_type, amount, category, date, comment).
· Данные не сохраняются между запусками программы.

---

4. Диаграммы потоков данных (DFD)

4.1 Элементы DFD (общие для обеих версий)

Элемент Обозначение
Источник Пользователь
Процессы 1. Ввод/добавление операции   2. Просмотр всех операций   3. Фильтрация операций   4. Формирование отчёта
Хранилище Ledger (список операций в памяти)
Выход Консоль (текстовый вывод для пользователя)

4.2 DFD уровня 1 для версии 1

Версия 1 выполняет минимальную валидацию (только проверка что сумма – число). Остальной ввод принимается без проверок.

```
Пользователь → [Процесс 1: Добавить операцию] → Ledger (запись)
Пользователь → [Процесс 2: Показать все] ← Ledger (чтение) → Пользователь
Пользователь → [Процесс 3: Фильтр] → Ledger (чтение) → Пользователь
Пользователь → [Процесс 4: Отчёт] → Ledger (чтение) → Пользователь
```

Особенности v1:

· Отсутствует валидация типа операции, даты, категории.
· Сравнение дат происходит как строк (лексикографически).
· Фильтр чувствителен к регистру категории.

4.3 DFD уровня 1 для версии 2

Версия 2 включает дополнительные проверяющие подпроцессы внутри «Добавить операцию» (валидация типа, суммы, даты, непустых полей). Фильтрация использует приведение категории к нижнему регистру.

```
Пользователь → [Процесс 1: Добавить операцию] 
                 → [1.1 Валидация типа] 
                 → [1.2 Валидация суммы (>0)] 
                 → [1.3 Валидация даты] 
                 → [1.4 Валидация непустой категории] 
                 → Ledger (запись)
Пользователь → [Процесс 2: Показать все] ← Ledger (чтение) → Пользователь
Пользователь → [Процесс 3: Фильтр] → Ledger (чтение) → Пользователь
Пользователь → [Процесс 4: Отчёт] → Ledger (чтение) → Пользователь
```

Рекомендация по построению:
Диаграммы выполнены в draw.io (файлы прилагаются к отчёту отдельно). Основное отличие – в v2 процесс добавления детализирован как вложенная DFD с валидационными блоками.

---

5. Блок-схемы алгоритмов

5.1 Алгоритм добавления операции (сравнение v1 и v2)

Блок-схема для v1:

```
Начало
  ↓
Ввод типа (income/expense)
  ↓
Ввод суммы
  ↓
Ввод категории
  ↓
Ввод даты
  ↓
Ввод комментария
  ↓
Попытка преобразовать сумму в float
  ↓
Успех? —Нет→ Вывод ошибки, возврат в меню
  ↓ Да
Создать словарь операции
  ↓
Добавить в список ledger
  ↓
Конец
```

Блок-схема для v2 (добавлены циклы валидации):

```
Начало
  ↓
Ввод типа → проверка: income/expense? —Нет→ повторить ввод
  ↓ Да
Ввод суммы → >0 и число? —Нет→ повторить ввод
  ↓ Да
Ввод категории → не пусто? —Нет→ повторить ввод
  ↓ Да
Ввод даты → формат YYYY-MM-DD? —Нет→ повторить ввод
  ↓ Да
Ввод комментария (опционально)
  ↓
Создать объект Transaction
  ↓
Добавить в список ledger
  ↓
Конец
```

5.2 Алгоритм фильтрации (общий для обеих версий, с учётом улучшений v2)

```
Начало
  ↓
Ввод даты «с» (опционально)
  ↓
Ввод даты «по» (опционально)
  ↓
Ввод категории (опционально)
  ↓
Ввод типа (опционально)
  ↓
Создать пустой список `result`
  ↓
Для каждой операции в ledger:
    ├─ если задана дата «с» и дата операции < дата «с» → пропустить
    ├─ если задана дата «по» и дата операции > дата «по» → пропустить
    ├─ если задана категория и категория операции != категория (без учёта регистра в v2) → пропустить
    ├─ если задан тип и тип операции != тип → пропустить
    └─ иначе добавить операцию в `result`
  ↓
Вывести `result`
  ↓
Конец
```

Примечание: в v1 сравнение дат строковое (может давать неверные результаты), регистр категории не игнорируется. В v2 категория приводится к нижнему регистру при сравнении.

---

6. Сравнительный анализ версий

Параметр Версия 1 Версия 2 Комментарий
Валидация типа Нет – принимает любую строку Есть – только income/expense, цикл до правильного ввода v2 устойчивее, предотвращает ошибочные типы
Проверка суммы Только на число (может быть 0 или отрицательной) 0 и число, цикл до коррекции v2 исключает нулевые и отрицательные суммы, что корректно для финансов
Проверка даты Нет – любая строка Строгая проверка формата через datetime.strptime v2 гарантирует корректные даты, важны для фильтрации по диапазону
Пустые значения Категория и комментарий могут быть пустыми Категория не может быть пустой (цикл input_non_empty) v2 повышает качество данных
Структура хранения Список словарей, нет типизации Список объектов Transaction, dataclass, аннотации типов v2 более читаема, легче расширять, меньше ошибок по ключам
Фильтр по категории С учётом регистра, нет приведения category.lower() – регистронезависимый v2 удобнее для пользователя
Сравнение дат Лексикографически (строки) Тоже строки, но формат YYYY-MM-DD гарантирует корректность v2 благодаря валидации формата работает правильно; в v1 возможно искажение
Обработка ошибок При ошибке суммы – выход из добавления Циклы повторного ввода до правильного значения v2 дружественнее к пользователю
Типизация Отсутствует Literal, Optional, List, Dict v2 упрощает статический анализ и самодокументацию
Устойчивость Низкая – легко нарушить логику Высокая – входные данные защищены от некорректного ввода v2 предпочтительнее для реального использования

Потенциальные проблемы в версии 1:

1. Отрицательная сумма – будет учтена как доход/расход с минусом, что исказит баланс.
2. Некорректная дата (например, 32.13.2025) – проходит в список, фильтр по диапазону сломается.
3. Тип операции с опечаткой (incom) – создаст операцию, которая не будет учтена в отчёте (не попадёт ни в доходы, ни в расходы).

---

7. Вопросы разработчику

1. Почему в версии 1 отсутствует строгая проверка типа операции, хотя это критично для подсчёта баланса?
2. Что произойдёт при вводе отрицательной суммы в версии 1? Почему не было добавлено ограничение amount > 0?
3. Почему дата хранится как строка, а не как объект datetime? В версии 2 формат проверяется, но тип остался строкой.
4. Что будет при большом количестве операций (например, 100 000)? Есть ли риск переполнения памяти или медленной фильтрации?
5. Почему в версии 1 фильтр по категории чувствителен к регистру? Это ожидаемо для пользователя?
6. В версии 2 функция filter_txs возвращает новый список, но исходный ledger не изменяется – зачем тогда нужен параметр date_from/to со значениями по умолчанию None, если внутри всё равно проверка?
7. Почему комментарий в версии 2 сделан необязательным, а категория – обязательной? Какое бизнес-правило это отражает?
8. Как обрабатывается ситуация, когда пользователь ввел дату «с» больше, чем «по»? Будет ли пустой результат или стоит подсказка?
9. В версии 1 функция show_all принимает аргумент items, но при вызове show_all(ledger) передаётся глобальный список – не возникнет ли путаницы, если в будущем добавится ещё один список?
10. Почему в обеих версиях данные не сохраняются в файл? Это учебное ограничение или планируется расширение?

---

8. Риски

Риск Описание Вероятность Влияние
Неправильный расчёт баланса из-за некорректного типа В v1 пользователь может ввести "incomee", операция добавится, но не попадёт ни в доходы, ни в расходы. Баланс будет неверным. Средняя Высокое
Ошибочная фильтрация по дате В v1 даты сравниваются как строки. "2025-02-01" > "2025-01-31" верно, но "2025-2-1" уже нет. Приводит к пропуску операций. Высокая Среднее
Нулевая или отрицательная сумма в v1 Пользователь может ввести -500 как расход, что увеличит баланс (так как доходы - (-500) = доходы +500). Абсурдная ситуация. Средняя Высокое
Пустая категория в v1 Затрудняет фильтрацию и группировку. Может быть пропущена при отчёте. Низкая Низкое
Чувствительность к регистру в фильтре v1 Пользователь введёт категорию «Еда», а сохранил «еда» – фильтр не сработает. Высокая Среднее
Отсутствие сохранения данных При случайном выходе все операции теряются. Это главный недостаток для практического применения. – Критическое
Неограниченный рост списка в памяти Нет ограничения на количество операций, при долгом использовании может заполнить память. Низкая Среднее
Отсутствие редактирования/удаления операций Пользователь не может исправить ошибку ввода, только завершить программу и начать заново. – Среднее

---

9. Участки кода, требующие внимания (с объяснением)

Версия 1:

· Строка 16: t = input("Тип (income/expense): ").strip() – нет проверки на допустимые значения. При вводе "in" операция будет потеряна для отчёта.
· Строка 24-27: try: amount = float(amount) except: print("Ошибка") – при ошибке функция возвращает None, но операция уже не добавляется. При этом нет цикла повторного ввода – пользователь вынужден заново выбирать пункт меню.
· Строка 58-61: if d1 and tx["date"] < d1 – строковое сравнение дат. Не гарантирует хронологический порядок, если формат отличается.

Версия 2:

· Строка 14: date: str – хоть и проверяется формат при вводе, но внутри остаётся строкой. При операциях сравнения дат может возникнуть проблема, если в будущем появятся даты из разных источников.
· Строка 77-79: if t not in (None, "income", "expense"): – после приведения к lower возможна потеря исходного регистра, но это не критично. Однако лучше было бы использовать тип Literal.
· Функция filter_txs (строка 58-71) – каждый раз создаёт новый список. При большом объёме данных это может быть неэффективно. Можно использовать генератор или итератор.

---

10. Вывод

В ходе лабораторной работы был проведён полный анализ двух версий консольного приложения MiniLedger. Версия 1 демонстрирует типичные ошибки начального этапа разработки: отсутствие валидации, ненадёжное сравнение дат, чувствительность к регистру. Версия 2 значительно улучшает качество за счёт циклов проверки ввода, строгой типизации и регистронезависимой фильтрации.

Построенные диаграммы потоков данных и блок-схемы наглядно показывают разницу в логике обработки. Сравнительная таблица подтверждает, что версия 2 устойчивее к ошибкам пользователя и更适合 для практического использования. Тем не менее, обе версии не сохраняют данные и не поддерживают редактирование – это основные направления для доработки.

Отчёт включает 10 вопросов для code-review, описание рисков и критических участков кода, что полностью соответствует заданию.