- Создание, редактирование, удаление счетов (
BankAccount) - Создание, редактирование, удаление категорий (
Category) - Создание, откатывание (удаление) операций по счетам (
Operation) - Автоматическое применение изменений баланса счёта при новой операции
- Возможность перерасчёта баланса всех счетов при обнаружении несоответствия / ошибки (путём вызова соответствующей функции)
- Хранение БД (репозиториев) локально в виде JSON файликов (может быть легко изменено в будущем)
Примечание: операции считаются неизменяемыми и не могут быть отредактированы. Откатывание операции происходит путём создания новой операции, которая отменяет предыдущую. При этом и исходная, и откатывающая операция удаляются из истории и репозитория. Для изменения операции рекомендуется откатить операцию и пересоздать её
- Аналитика по
- доходы минус расходы (
GetNetIncome) - группировка по категориям, все доходы минус все расходы категории (
GetTotalsGrouped) - самая крупная категория по расходам (
GetTopSpending) - самая крупная категория по доходам (
GetTopEarning)
вся аналитика считается по выбранному периоду (дата+время) и выбранным счетам (можно выбрать несколько)
- доходы минус расходы (
- Импорт данных из
Json,YAML,CSV - Экспорт данных в
Json,YAML,CSVЭкспорт в CSV реализован путём экспорта трёх разных таблиц в три разных файла (с фиксированными названиями) в одной папке, путь к которой указывается приложением
- Статистика по времени исполнения пользовательских сценариев (команд)
- Кэширование данных БД в ОЗУ через прокси-обертку над основным репозиторием
- Абстрагирование от файловой системы через
IFileAccessor,IDirectoryAccessor. Позволяет использовать, например, S3 хранилища без модификации кода
- Single Responsibility Principle
BankAccountFacade- только работа со счетамиCategoryFacade- только работа с категориямиOperationFacade- только работа с операциямиAnalyticsFacade- только аналитика по счетам/категориям/операциям, не изменяет ничего из перечисленногоIRepositoryCrudи его реализации - хранение данных (счета, категории, операции)IFileAccessorиIDirectoryAccessor- взаимодействие с файловыми системами (необязательно локальными, можно и с S3, облачными хранилищами)
- Open Closed Principle
- легко добавить новый формат экспорта данных (новый
IExportVisitor) без редактирования остального кода - легко добавить новый формат импорта (новый наследник
BankSystemImporter) без редактирования остального кода - новая аналитика - новая стратегия аналитики
IAnalyticStrategy - можно добавить реализацию для любого интерфейса, не меняя его код (и код тех, кто его использует)
- легко добавить новый формат экспорта данных (новый
- Liskov Substitution Principle
- все реализации одного интерфейса взаимозаменяемы, например,
JsonExportVisitor,YamlExportVisitorмогут быть использованы там, где ожидаетсяIExportVisitor. то же самое и с наследникамиBankSystemImporter,CachedRepositoryиJsonFileRepositoryи т.д.
- все реализации одного интерфейса взаимозаменяемы, например,
- Interface Segregation Principle
IEntity,IRepositoryCrud,IExportVisitor,IBankSystemFactory- все эти интерфейсы раздельны, классы могут использовать (или реализовывать) только нужные- интерфейсы узкоспециализированы
- Dependency Inversion Principle
- код зависит от абстракций (
IRepositoryCrud,IBankSystemFactory,ICommand), а не от реализаций - зависимости внедряются через конструкторы
- консольное приложение использует DI контейнер (из
Microsoft.Extensions.DependencyInjection) для управления зависимостями, их сроками жизни
- код зависит от абстракций (
- Controller
- Фасады (
BankAccountFacade,CategoryFacade,OperationFacadeи т.д.) и команды (реализацииICommand) являются контроллерами разных уровней (фасады для прикладного, команды для пользовательских сценариев)
- Фасады (
- Creator
- Создание сущностей и валидация параметров происходит через фабрики (реализации
IBankSystemFactory)
- Создание сущностей и валидация параметров происходит через фабрики (реализации
- High Cohesion
Storage- отвечает за хранение данных (репозитории, хранилища основанные на файлах -FileBased)Domain/Model- доменные сущностиService- фасады с бизнес логикой, используют репозитории и фабрики
- Low Coupling
- Компоненты связаны через интерфейсы, а не через реализации
- Для управления зависимостями используется DI контейнер
- Хранилище изолировано от основного кода (может быть использована любая БД)
- Pure Fabrication
- Команды (реализации
ICommand) - Строитель операций (
OperationBuilder)
- Команды (реализации
- Фасад
- Где:
BankAccountFacade,CategoryFacade,OperationFacade,AnalyticsFacade - Зачем: Единый интерфейс для группы похожих операций, сокрытие внутренней логики
- Где:
- Фабрика
- Где:
BankSystemFactory - Зачем: Централизация создания объектов, валидация параметров, корректность состояния объектов, инкапсулирует логику создания случайного ID (через Guid.NewGuid())
- Где:
- Команда
- Где:
ICommandи его реализации вCommand/ - Зачем: Инкапсулировать действия (пользовательские сценарии), единый интерфейс работы с ними и выполнения, возможность подключать дополнительные метрики (время работы, логирование) через декораторы
- Где:
- Декоратор
- Где:
TimePrintingCommandDecorator - Зачем: Добавить функциональность командам (вывод времени работы) без изменения основного кода
- Где:
- Шаблонный метод
- Где:
BankSystemImporterи его наследники вImport/ - Зачем: Основная логика процесса (сохранение импортированных данных в репозиторий и их валидация) в
BankSystemImporterи вариативная часть (чтение, десериализация) в наследниках
- Где:
- Посетитель
- Где:
IExportVisitorи его реализации вExport/ - Зачем: Добавление новой логики классов без изменения их кода.
- Где:
- Прокси
- Где:
CachedRepository - Зачем: Ускорить считывание данных из БД путём кэширования. Может работать с любым репозиторием (наследник
IRepositoryCrud) без изменения его кода и кода клиентов
- Где:
- Стратегия
- Где:
IAnalyticStrategyи его реализации, возможно, некоторые другие интерфейсы - Зачем: Семейство взаимозаменяемых алгоритмов со схожим интерфейсом. Стратегии аналитики использует
AnalyticsFacade, использует нужную стратегию, может их комбинировать
- Где:
- Строитель
- Где:
OperationBuilder - Зачем: Более удобное и поэтапное создание операций (у них много аргументов). Есть удобные вариации некоторых шагов (например,
RightNow()автоматически проставит текущую дату/время, не нужно самому её передавать)
- Где:
- Repository
- Где:
IRepositoryCrudи его реализации:JsonFileRepository,CachedRepository - Зачем: Отделить домен от способов хранения данных, абстракция доступа к ним
- Клонировать репозиторий проекта
- Запустить
dotnet build - Скопировать папку
importиз корня в папку, в которой находится исполняемый файл (.exe). Необходимо для показа импорта в демке - Запустить
dotnet run --project HseBank