C++ · Desktop
CadflowBankSystem — Banking system in C++/MFC
A company set me a technical challenge: build a desktop banking system in native C++, with no frameworks. This is the result.
Context
Solved alone in about a month. C++ with MFC, on Windows.
The problem
Accounts, transactions, transfers and balance queries in a desktop application. No web framework, no ORM, no garbage collector: memory management, UI state and data persistence all become the responsibility of whoever writes the code.
Technical decisions
Domain model kept separate from the UI
The Account, Transaction and BankManager classes do not know a window exists. All the banking logic lives in code that imports nothing from MFC, and the dialogs only collect data, call the model and show the result. In MFC the easy path is writing the logic inside the button's handler, because that is where the data already is. It works, and then the same rule exists in three dialogs with three variations.
Persistence in a text file
Data is stored as plain text. It was quick to write and lets you read the contents without tools, which helps when debugging. The cost is that everything read back has to be validated by hand, and any format error only shows up once the program is already running.
Native C++, with what that implies
With no garbage collector, every object's lifetime is a conscious decision. It was the project that forced me to understand what languages with automatic memory management had let me ignore.
What went wrong
MFC was half the problem. It is an old library, with its own conventions, message maps and bindings between controls and variables that resemble nothing I had used before. I spent more time working out how it is done than writing the logic itself.
The other half was deciding what each class should hold. When you start with Account, Transaction and BankManager on a blank page, every operation could live in three different places and all three look reasonable at first. Choosing badly means discovering two weeks later that a simple rule needs data that ended up on the other side.
I redid that split more than once, until it stopped getting in my way. It was the first time I understood that designing classes is a decision about who knows what, not about where to file the code.
Outcome
Delivered, with a positive response from the company.
What I'd do differently
I would swap the text file for SQLite. Storing as text was quick to write, but it forces you to validate everything read back by hand, and a corrupted file only announces itself when it is already too late. An embedded database solves that without adding a dependency the application could not carry with it.