Загрузка данных
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, описание рисков и критических участков кода, что полностью соответствует заданию.