mirror of
https://github.com/wahyd4/cash-code-test.git
synced 2026-08-09 05:16:05 +10:00
108 lines
3.4 KiB
Markdown
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
|
|
```
|