Files
2019-12-17 07:25:03 +11:00

108 lines
3.4 KiB
Markdown

# Cash
- [Cash](#cash)
- [About the solution](#about-the-solution)
- [Stack](#stack)
- [Design](#design)
- [Assumptions & Trade offs](#assumptions-amp-trade-offs)
- [What would I do more if I have more time](#what-would-i-do-more-if-i-have-more-time)
- [How to run](#how-to-run)
- [docker-compose](#docker-compose)
- [The classic Way](#the-classic-way)
- [Run the application against custom inputs](#run-the-application-against-custom-inputs)
## About the solution
### Stack
- Go
- [Logrus](https://github.com/sirupsen/logrus) for better logging
- [testify/assert](https://github.com/stretchr/testify) some test assertion helpers
### Design
In my design, there are `4` core domains,
- Application, represents the cash application which can load inputs and execute actions.
- BankAccount, contains the information of a single bank account and basic deposit/withdraw actions to the user.
- Bank, the bank entity which holds all the bank accounts and the total balance. All the `deposit/withdraw` actions go to bank and then acknowledged by bank account.
- Command, represent a single action. e.g. `deposit`, `withdraw`, `balance`. way. All commands have been implemented the `ICommand` interface with `Run(bank *Bank)` method, so they can be processed by the application in a standard
The steps below shows how the application works.
1. When we start this application it will initialise a `bank` and the `cash application` instance.
2. All the actions recorded in a input file will be parsed and transferred to `command`
3. The Cash application will take the commands as input, process them and print out some basic information.
### Assumptions & Trade offs
In order to start implementing this project, I have made a few assumptions below:
- Only one seesion for any user at any single moment, which means there will no dirty reads/writes for a user
- All the actions will be loaded through a input text file and will be processed following the sequence order, so it means the application currently can only run one command at a time.
- I use Australian Dollar($) as the currency type, use `int` to represent `cent` as the currency unit.
### What would I do more if I have more time
There are two things I want to do most in terms of building a proper cash app if I have more time.
- Make it to be a CLI and support multiple users login and run actions at the same time.
- Add some basic locks for depositing and withdrawing operations at both user and bank level.
## How to run
### docker-compose
Please make sure you have `docker` and `docker-compose` installed
Then just simply run the commands below
```bash
# One command to run application
docker-compose up
# If you want to run another failure case with withdrawing more money than the user has
docker-compose run cash go run main.go no_enough_money.txt
# Run tests
docker-compose run cash go test ./... -cover
```
Or you can try the classic way.
### The classic Way
Similar, you should have `go` installed before we start
```bash
# Install all dependencies
go mod download
# Run application
go run main.go input.txt
# Run Tests
go test ./... -cover
```
### Run the application against custom inputs
You can also build your custom input and define as many commands as you want.
There is a example below with single bank account.
```
OPEN_ACCOUNT Tom
DEPOSIT Tom 520.30
WITHDRAW Tom 340.00
BALANCE Tom
TOTAL_BALANCE
```
Then test it
```bash
docker-compose run cash go run main.go yourfile
```