Just set the VendingMachine project as the startup one and run from VS.
Frontend
- ReactJS
Backend
- .net core
- C#
- Swagger for API testing and documentation.
To have a virtual vending machine that would behave like a real one.
To store the coins in the wallets, I injected singleton services which have the data they need so I don’t have to worry about the state of the coins.
Then for the products list, I simulated they are in a repository and implemented that in a way that if they end up being in a database, textfile or whatever it is easy to switch.
I built it in four layers:
-
API - holds the controllers and the DI configuration. Also Swagger was added to have a more readeable documentation accessing the
/swagger
endpoint. This layer references the Application & Domain layers. -
Application - holds the services that run the logic of the application and communicate with the domain. Here’s where all the processing happen. This layer references the Domain layer.
-
Domain - holds the models and behavior definitions needed for the app to work.
-
Persistence - holds the implementation of the
IProductRepository
. This layer references the Application & Domain layers.
The project has essentially three models in the Domain layer:
-
Product - represents the Product entity and its behavior, in this case it has the ability to take itself and to substract the unit taken.
-
UserWalletService - represents the user's wallet and its behavior, keeps the collection of coins updated and handles them.
-
MachineWalletService - represents the vending-machine's wallet and it has the exact same behavior as the user's wallet, with the difference that the
MachineWallet
starts with a default amount of coins.
Each of these models has its service in the Application layer that handles them.
Additionally I added three custom exceptions to handle three validation scenarios:
-
InvalidCoinException - to avoid invalid coins to be inserted.
-
ProductNotAllowedException - to prevent for a product to be sold if the user has not entered an enough amount or if there’s no units left for the given product.
-
NoChangeExceptions - will happen if the vending machine has not enough coins to return the change.
Since both wallets are based on the same base-class, I built two sets of tests:
-
WalletTest.cs - Tests the functionality of the WalletService (coins and amount management), and since the user and the vending machine wallets implements the same logic, one is enough.
-
ProductsTest.cs - Tests the functionality of the ProductService to ensure that the listing and the Units management work as expected.
- Added a logging to register exceptions and monitor.
- Improved the flow for the method
ProductsController.Take
. I don't like having to worry about removing the coins from the machine wallet if it gets to this catchcatch (NoChangeException ex)
. - Improved the UI, probably used Redux.